initial import
[vuplus_webkit] / Source / JavaScriptCore / runtime / Executable.h
1 /*
2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef Executable_h
27 #define Executable_h
28
29 #include "CallData.h"
30 #include "JSFunction.h"
31 #include "Interpreter.h"
32 #include "Nodes.h"
33 #include "SamplingTool.h"
34 #include <wtf/PassOwnPtr.h>
35
36 namespace JSC {
37
38     class CodeBlock;
39     class Debugger;
40     class EvalCodeBlock;
41     class FunctionCodeBlock;
42     class ProgramCodeBlock;
43     class ScopeChainNode;
44
45     struct ExceptionInfo;
46     
47     enum CodeSpecializationKind { CodeForCall, CodeForConstruct };
48
49     class ExecutableBase : public JSCell {
50         friend class JIT;
51
52     protected:
53         static const int NUM_PARAMETERS_IS_HOST = 0;
54         static const int NUM_PARAMETERS_NOT_COMPILED = -1;
55
56         ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters)
57             : JSCell(globalData, structure)
58             , m_numParametersForCall(numParameters)
59             , m_numParametersForConstruct(numParameters)
60         {
61         }
62
63         void finishCreation(JSGlobalData& globalData)
64         {
65             Base::finishCreation(globalData);
66             Weak<ExecutableBase> finalizer(globalData, this, executableFinalizer());
67             finalizer.leakHandle();
68         }
69         
70     public:
71         typedef JSCell Base;
72
73         static ExecutableBase* create(JSGlobalData& globalData, Structure* structure, int numParameters)
74         {
75             ExecutableBase* executable = new (allocateCell<ExecutableBase>(globalData.heap)) ExecutableBase(globalData, structure, numParameters);
76             executable->finishCreation(globalData);
77             return executable;
78         }
79
80         bool isHostFunction() const
81         {
82             ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
83             return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
84         }
85
86         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
87         
88         static const ClassInfo s_info;
89
90         virtual void clearCode();
91
92     protected:
93         static const unsigned StructureFlags = 0;
94         int m_numParametersForCall;
95         int m_numParametersForConstruct;
96
97 #if ENABLE(JIT)
98     public:
99         JITCode& generatedJITCodeForCall()
100         {
101             ASSERT(m_jitCodeForCall);
102             return m_jitCodeForCall;
103         }
104
105         JITCode& generatedJITCodeForConstruct()
106         {
107             ASSERT(m_jitCodeForConstruct);
108             return m_jitCodeForConstruct;
109         }
110         
111         JITCode& generatedJITCodeFor(CodeSpecializationKind kind)
112         {
113             if (kind == CodeForCall)
114                 return generatedJITCodeForCall();
115             ASSERT(kind == CodeForConstruct);
116             return generatedJITCodeForConstruct();
117         }
118
119         MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
120         {
121             ASSERT(m_jitCodeForCall);
122             ASSERT(m_jitCodeForCallWithArityCheck);
123             return m_jitCodeForCallWithArityCheck;
124         }
125
126         MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
127         {
128             ASSERT(m_jitCodeForConstruct);
129             ASSERT(m_jitCodeForConstructWithArityCheck);
130             return m_jitCodeForConstructWithArityCheck;
131         }
132         
133         MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
134         {
135             if (kind == CodeForCall)
136                 return generatedJITCodeForCallWithArityCheck();
137             ASSERT(kind == CodeForConstruct);
138             return generatedJITCodeForConstructWithArityCheck();
139         }
140         
141         bool hasJITCodeForCall() const
142         {
143             return m_numParametersForCall >= 0;
144         }
145         
146         bool hasJITCodeForConstruct() const
147         {
148             return m_numParametersForConstruct >= 0;
149         }
150         
151         bool hasJITCodeFor(CodeSpecializationKind kind) const
152         {
153             if (kind == CodeForCall)
154                 return hasJITCodeForCall();
155             ASSERT(kind == CodeForConstruct);
156             return hasJITCodeForConstruct();
157         }
158
159     protected:
160         JITCode m_jitCodeForCall;
161         JITCode m_jitCodeForConstruct;
162         MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
163         MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
164 #endif
165         
166     private:
167         static WeakHandleOwner* executableFinalizer();
168     };
169
170     class NativeExecutable : public ExecutableBase {
171         friend class JIT;
172     public:
173         typedef ExecutableBase Base;
174
175 #if ENABLE(JIT)
176         static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor)
177         {
178             NativeExecutable* executable;
179             if (!callThunk) {
180                 executable = new (allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
181                 executable->finishCreation(globalData, JITCode(), JITCode());
182             } else {
183                 executable = new (allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
184                 executable->finishCreation(globalData, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk));
185             }
186             return executable;
187         }
188 #else
189         static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
190         {
191             NativeExecutable* executable = new (allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
192             executable->finishCreation(globalData);
193             return executable;
194         }
195 #endif
196
197         ~NativeExecutable();
198
199         NativeFunction function() { return m_function; }
200
201         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
202         
203         static const ClassInfo s_info;
204
205     protected:
206 #if ENABLE(JIT)
207         void finishCreation(JSGlobalData& globalData, JITCode callThunk, JITCode constructThunk)
208         {
209             Base::finishCreation(globalData);
210             m_jitCodeForCall = callThunk;
211             m_jitCodeForConstruct = constructThunk;
212             m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
213             m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
214         }
215 #endif
216  
217     private:
218 #if ENABLE(JIT)
219         NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
220             : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
221             , m_function(function)
222             , m_constructor(constructor)
223         {
224         }
225 #else
226         NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
227             : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
228             , m_function(function)
229             , m_constructor(constructor)
230         {
231         }
232 #endif
233
234         NativeFunction m_function;
235         // Probably should be a NativeConstructor, but this will currently require rewriting the JIT
236         // trampoline. It may be easier to make NativeFunction be passed 'this' as a part of the ArgList.
237         NativeFunction m_constructor;
238     };
239
240     class ScriptExecutable : public ExecutableBase {
241     public:
242         typedef ExecutableBase Base;
243
244         ScriptExecutable(Structure* structure, JSGlobalData& globalData, const SourceCode& source, bool isInStrictContext)
245             : ExecutableBase(globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
246             , m_source(source)
247             , m_features(isInStrictContext ? StrictModeFeature : 0)
248         {
249         }
250
251         ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
252             : ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED)
253             , m_source(source)
254             , m_features(isInStrictContext ? StrictModeFeature : 0)
255         {
256         }
257
258         const SourceCode& source() { return m_source; }
259         intptr_t sourceID() const { return m_source.provider()->asID(); }
260         const UString& sourceURL() const { return m_source.provider()->url(); }
261         int lineNo() const { return m_firstLine; }
262         int lastLine() const { return m_lastLine; }
263
264         bool usesEval() const { return m_features & EvalFeature; }
265         bool usesArguments() const { return m_features & ArgumentsFeature; }
266         bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
267         bool isStrictMode() const { return m_features & StrictModeFeature; }
268
269         virtual void unlinkCalls() = 0;
270         
271         static const ClassInfo s_info;
272
273     protected:
274         void finishCreation(JSGlobalData& globalData)
275         {
276             Base::finishCreation(globalData);
277 #if ENABLE(CODEBLOCK_SAMPLING)
278             if (SamplingTool* sampler = globalData.interpreter->sampler())
279                 sampler->notifyOfScope(globalData, this);
280 #endif
281         }
282
283         void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
284         {
285             m_features = features;
286             m_hasCapturedVariables = hasCapturedVariables;
287             m_firstLine = firstLine;
288             m_lastLine = lastLine;
289         }
290
291         SourceCode m_source;
292         CodeFeatures m_features;
293         bool m_hasCapturedVariables;
294         int m_firstLine;
295         int m_lastLine;
296     };
297
298     class EvalExecutable : public ScriptExecutable {
299     public:
300         typedef ScriptExecutable Base;
301
302         ~EvalExecutable();
303
304         JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
305         {
306             ASSERT(exec->globalData().dynamicGlobalObject);
307             JSObject* error = 0;
308             if (!m_evalCodeBlock)
309                 error = compileInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
310             ASSERT(!error == !!m_evalCodeBlock);
311             return error;
312         }
313         
314         JSObject* compileOptimized(ExecState*, ScopeChainNode*);
315
316         EvalCodeBlock& generatedBytecode()
317         {
318             ASSERT(m_evalCodeBlock);
319             return *m_evalCodeBlock;
320         }
321
322         static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) 
323         {
324             EvalExecutable* executable = new (allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
325             executable->finishCreation(exec->globalData());
326             return executable;
327         }
328
329 #if ENABLE(JIT)
330         JITCode& generatedJITCode()
331         {
332             return generatedJITCodeForCall();
333         }
334 #endif
335         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
336         {
337             return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info);
338         }
339         
340         static const ClassInfo s_info;
341
342     protected:
343         virtual void clearCode();
344
345     private:
346         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
347         EvalExecutable(ExecState*, const SourceCode&, bool);
348
349         JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
350         virtual void visitChildren(SlotVisitor&);
351         void unlinkCalls();
352
353         OwnPtr<EvalCodeBlock> m_evalCodeBlock;
354     };
355
356     class ProgramExecutable : public ScriptExecutable {
357     public:
358         typedef ScriptExecutable Base;
359
360         static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
361         {
362             ProgramExecutable* executable = new (allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
363             executable->finishCreation(exec->globalData());
364             return executable;
365         }
366
367         ~ProgramExecutable();
368
369         JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
370         {
371             ASSERT(exec->globalData().dynamicGlobalObject);
372             JSObject* error = 0;
373             if (!m_programCodeBlock)
374                 error = compileInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
375             ASSERT(!error == !!m_programCodeBlock);
376             return error;
377         }
378
379         JSObject* compileOptimized(ExecState*, ScopeChainNode*);
380
381         ProgramCodeBlock& generatedBytecode()
382         {
383             ASSERT(m_programCodeBlock);
384             return *m_programCodeBlock;
385         }
386
387         JSObject* checkSyntax(ExecState*);
388
389 #if ENABLE(JIT)
390         JITCode& generatedJITCode()
391         {
392             return generatedJITCodeForCall();
393         }
394 #endif
395         
396         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
397         {
398             return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info);
399         }
400         
401         static const ClassInfo s_info;
402         
403     protected:
404         virtual void clearCode();
405
406     private:
407         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
408         ProgramExecutable(ExecState*, const SourceCode&);
409
410         JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
411         virtual void visitChildren(SlotVisitor&);
412         void unlinkCalls();
413
414         OwnPtr<ProgramCodeBlock> m_programCodeBlock;
415     };
416
417     class FunctionExecutable : public ScriptExecutable {
418         friend class JIT;
419     public:
420         typedef ScriptExecutable Base;
421
422         static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
423         {
424             FunctionExecutable* executable = new (allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext);
425             executable->finishCreation(exec->globalData(), name, firstLine, lastLine);
426             return executable;
427         }
428
429         static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
430         {
431             FunctionExecutable* executable = new (allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext);
432             executable->finishCreation(globalData, name, firstLine, lastLine);
433             return executable;
434         }
435
436         JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
437         {
438             return JSFunction::create(exec, this, scopeChain);
439         }
440         
441         // Returns either call or construct bytecode. This can be appropriate
442         // for answering questions that that don't vary between call and construct --
443         // for example, argumentsRegister().
444         FunctionCodeBlock& generatedBytecode()
445         {
446             if (m_codeBlockForCall)
447                 return *m_codeBlockForCall;
448             ASSERT(m_codeBlockForConstruct);
449             return *m_codeBlockForConstruct;
450         }
451
452         JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode, ExecState* calleeArgsExec = 0)
453         {
454             ASSERT(exec->globalData().dynamicGlobalObject);
455             JSObject* error = 0;
456             if (!m_codeBlockForCall)
457                 error = compileForCallInternal(exec, scopeChainNode, calleeArgsExec, JITCode::bottomTierJIT());
458             ASSERT(!error == !!m_codeBlockForCall);
459             return error;
460         }
461
462         JSObject* compileOptimizedForCall(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec = 0);
463
464         bool isGeneratedForCall() const
465         {
466             return m_codeBlockForCall;
467         }
468
469         FunctionCodeBlock& generatedBytecodeForCall()
470         {
471             ASSERT(m_codeBlockForCall);
472             return *m_codeBlockForCall;
473         }
474
475         JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
476         {
477             ASSERT(exec->globalData().dynamicGlobalObject);
478             JSObject* error = 0;
479             if (!m_codeBlockForConstruct)
480                 error = compileForConstructInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
481             ASSERT(!error == !!m_codeBlockForConstruct);
482             return error;
483         }
484
485         JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*);
486
487         bool isGeneratedForConstruct() const
488         {
489             return m_codeBlockForConstruct;
490         }
491
492         FunctionCodeBlock& generatedBytecodeForConstruct()
493         {
494             ASSERT(m_codeBlockForConstruct);
495             return *m_codeBlockForConstruct;
496         }
497         
498         JSObject* compileFor(ExecState* exec, ScopeChainNode* scopeChainNode, CodeSpecializationKind kind)
499         {
500             // compileFor should only be called with a callframe set up to call this function,
501             // since we will make speculative optimizations based on the arguments.
502             ASSERT(exec->callee());
503             ASSERT(exec->callee()->inherits(&JSFunction::s_info));
504             ASSERT(asFunction(exec->callee())->jsExecutable() == this);
505
506             if (kind == CodeForCall)
507                 return compileForCall(exec, scopeChainNode, exec);
508             ASSERT(kind == CodeForConstruct);
509             return compileForConstruct(exec, scopeChainNode);
510         }
511         
512         JSObject* compileOptimizedFor(ExecState* exec, ScopeChainNode* scopeChainNode, CodeSpecializationKind kind)
513         {
514             // compileOptimizedFor should only be called with a callframe set up to call this function,
515             // since we will make speculative optimizations based on the arguments.
516             ASSERT(exec->callee());
517             ASSERT(exec->callee()->inherits(&JSFunction::s_info));
518             ASSERT(asFunction(exec->callee())->jsExecutable() == this);
519             
520             if (kind == CodeForCall)
521                 return compileOptimizedForCall(exec, scopeChainNode, exec);
522             ASSERT(kind == CodeForConstruct);
523             return compileOptimizedForConstruct(exec, scopeChainNode);
524         }
525         
526         bool isGeneratedFor(CodeSpecializationKind kind)
527         {
528             if (kind == CodeForCall)
529                 return isGeneratedForCall();
530             ASSERT(kind == CodeForConstruct);
531             return isGeneratedForConstruct();
532         }
533         
534         FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind)
535         {
536             if (kind == CodeForCall)
537                 return generatedBytecodeForCall();
538             ASSERT(kind == CodeForConstruct);
539             return generatedBytecodeForConstruct();
540         }
541
542         const Identifier& name() { return m_name; }
543         JSString* nameValue() const { return m_nameValue.get(); }
544         size_t parameterCount() const { return m_parameters->size(); }
545         unsigned capturedVariableCount() const { return m_numCapturedVariables; }
546         UString paramString() const;
547         SharedSymbolTable* symbolTable() const { return m_symbolTable; }
548
549         void discardCode();
550         void visitChildren(SlotVisitor&);
551         static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
552         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
553         {
554             return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info);
555         }
556         
557         static const ClassInfo s_info;
558         
559     protected:
560         virtual void clearCode();
561
562         void finishCreation(JSGlobalData& globalData, const Identifier& name, int firstLine, int lastLine)
563         {
564             Base::finishCreation(globalData);
565             m_firstLine = firstLine;
566             m_lastLine = lastLine;
567             m_nameValue.set(globalData, this, jsString(&globalData, name.ustring()));
568         }
569
570     private:
571         FunctionExecutable(JSGlobalData&, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
572         FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
573
574         JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec, JITCode::JITType);
575         JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
576         
577         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
578         unsigned m_numCapturedVariables : 31;
579         bool m_forceUsesArguments : 1;
580         void unlinkCalls();
581
582         RefPtr<FunctionParameters> m_parameters;
583         OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
584         OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
585         Identifier m_name;
586         WriteBarrier<JSString> m_nameValue;
587         SharedSymbolTable* m_symbolTable;
588     };
589
590     inline FunctionExecutable* JSFunction::jsExecutable() const
591     {
592         ASSERT(!isHostFunctionNonInline());
593         return static_cast<FunctionExecutable*>(m_executable.get());
594     }
595
596     inline bool JSFunction::isHostFunction() const
597     {
598         ASSERT(m_executable);
599         return m_executable->isHostFunction();
600     }
601
602     inline NativeFunction JSFunction::nativeFunction()
603     {
604         ASSERT(isHostFunction());
605         return static_cast<NativeExecutable*>(m_executable.get())->function();
606     }
607
608     inline bool isHostFunction(JSGlobalData& globalData, JSValue value, NativeFunction nativeFunction)
609     {
610         JSFunction* function = static_cast<JSFunction*>(getJSFunction(globalData, value));
611         if (!function || !function->isHostFunction())
612             return false;
613         return function->nativeFunction() == nativeFunction;
614     }
615
616 }
617
618 #endif