diff options
Diffstat (limited to 'Source/JavaScriptCore/interpreter')
-rw-r--r-- | Source/JavaScriptCore/interpreter/AbstractPC.cpp | 55 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/AbstractPC.h | 91 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/CallFrame.cpp | 100 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/CallFrame.h | 23 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/Interpreter.cpp | 93 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/Interpreter.h | 16 |
6 files changed, 292 insertions, 86 deletions
diff --git a/Source/JavaScriptCore/interpreter/AbstractPC.cpp b/Source/JavaScriptCore/interpreter/AbstractPC.cpp new file mode 100644 index 000000000..863915bda --- /dev/null +++ b/Source/JavaScriptCore/interpreter/AbstractPC.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AbstractPC.h" + +#include "CallFrame.h" +#include "JSGlobalData.h" +#include "JSObject.h" +#include "ScopeChain.h" + +namespace JSC { + +AbstractPC::AbstractPC(JSGlobalData& globalData, ExecState* exec) +{ + UNUSED_PARAM(globalData); + +#if ENABLE(JIT) + if (globalData.canUseJIT()) { + m_pointer = exec->returnPC().value(); + m_mode = JIT; + return; + } +#endif + +#if ENABLE(INTERPRETER) + m_pointer = exec->returnVPC(); + m_mode = Interpreter; +#endif +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/interpreter/AbstractPC.h b/Source/JavaScriptCore/interpreter/AbstractPC.h new file mode 100644 index 000000000..dffaaf343 --- /dev/null +++ b/Source/JavaScriptCore/interpreter/AbstractPC.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef AbstractPC_h +#define AbstractPC_h + +#include "MacroAssemblerCodeRef.h" +#include <wtf/Platform.h> + +namespace JSC { + +class JSGlobalData; +class ExecState; +struct Instruction; + +class AbstractPC { +public: + AbstractPC() + : m_pointer(0) + , m_mode(None) + { + } + + AbstractPC(JSGlobalData&, ExecState*); + +#if ENABLE(JIT) + AbstractPC(ReturnAddressPtr ptr) + : m_pointer(ptr.value()) + , m_mode(JIT) + { + } + + bool hasJITReturnAddress() const { return m_mode == JIT; } + ReturnAddressPtr jitReturnAddress() const + { + ASSERT(hasJITReturnAddress()); + return ReturnAddressPtr(m_pointer); + } +#endif + +#if ENABLE(INTERPRETER) + AbstractPC(Instruction* vPC) + : m_pointer(vPC) + , m_mode(Interpreter) + { + } + + bool hasInterpreterReturnAddress() const { return m_mode == Interpreter; } + Instruction* interpreterReturnAddress() const + { + ASSERT(hasInterpreterReturnAddress()); + return static_cast<Instruction*>(m_pointer); + } +#endif + + bool isSet() const { return m_mode != None; } + bool operator!() const { return !isSet(); } + +private: + void* m_pointer; + + enum Mode { None, JIT, Interpreter }; + Mode m_mode; +}; + +} // namespace JSC + +#endif // AbstractPC_h + diff --git a/Source/JavaScriptCore/interpreter/CallFrame.cpp b/Source/JavaScriptCore/interpreter/CallFrame.cpp index 6dba77898..3ef5bd26f 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.cpp +++ b/Source/JavaScriptCore/interpreter/CallFrame.cpp @@ -61,53 +61,66 @@ bool CallFrame::isInlineCallFrameSlow() JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell); return calleeAsFunction->executable() != codeBlock()->ownerExecutable(); } - -CallFrame* CallFrame::trueCallerFrame() + +CallFrame* CallFrame::trueCallFrame(AbstractPC pc) { - // this -> The callee; this is either an inlined callee in which case it already has - // a pointer to the true caller. Otherwise it contains current PC in the machine - // caller. - // - // machineCaller -> The caller according to the machine, which may be zero or - // more frames above the true caller due to inlining. - // - // trueCaller -> The real caller. - // Am I an inline call frame? If so, we're done. if (isInlineCallFrame()) - return callerFrame(); + return this; - // I am a machine call frame, so the question is: is my caller a machine call frame - // that has inlines or a machine call frame that doesn't? - CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag(); - if (!machineCaller) - return 0; - ASSERT(!machineCaller->isInlineCallFrame()); - if (!machineCaller->codeBlock()) - return machineCaller; - if (!machineCaller->codeBlock()->hasCodeOrigins()) - return machineCaller; // No inlining, so machineCaller == trueCaller + // If I don't have a code block, then I'm not DFG code, so I'm the true call frame. + CodeBlock* machineCodeBlock = codeBlock(); + if (!machineCodeBlock) + return this; - // Figure out where the caller frame would have gone relative to the machine - // caller, and rematerialize it. Do so for the entire inline stack. + // If the code block does not have any code origins, then there was no inlining, so + // I'm done. + if (!machineCodeBlock->hasCodeOrigins()) + return this; - CodeOrigin codeOrigin = machineCaller->codeBlock()->codeOriginForReturn(returnPC()); + // At this point the PC must be due either to the DFG, or it must be unset. + ASSERT(pc.hasJITReturnAddress() || !pc); + + // Try to determine the CodeOrigin. If we don't have a pc set then the only way + // that this makes sense is if the CodeOrigin index was set in the call frame. + // FIXME: Note that you will see "Not currently in inlined code" comments below. + // Currently, we do not record code origins for code that is not inlined, because + // the only thing that we use code origins for is determining the inline stack. + // But in the future, we'll want to use this same functionality (having a code + // origin mapping for any calls out of JIT code) to determine the PC at any point + // in the stack even if not in inlined code. When that happens, the code below + // will have to change the way it detects the presence of inlining: it will always + // get a code origin, but sometimes, that code origin will not have an inline call + // frame. In that case, this method should bail and return this. + CodeOrigin codeOrigin; + if (pc.isSet()) { + ReturnAddressPtr currentReturnPC = pc.jitReturnAddress(); + + if (!machineCodeBlock->codeOriginForReturn(currentReturnPC, codeOrigin)) + return this; // Not currently in inlined code. + } else { + unsigned index = codeOriginIndexForDFGWithInlining(); + if (index == UINT_MAX) + return this; // Not currently in inlined code. + + codeOrigin = machineCodeBlock->codeOrigin(index); + } for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) { InlineCallFrame* nextInlineCallFrame = inlineCallFrame->caller.inlineCallFrame; - CallFrame* inlinedCaller = machineCaller + inlineCallFrame->stackOffset; + CallFrame* inlinedCaller = this + inlineCallFrame->stackOffset; JSFunction* calleeAsFunction = inlineCallFrame->callee.get(); // Fill in the inlinedCaller - inlinedCaller->setCodeBlock(machineCaller->codeBlock()); + inlinedCaller->setCodeBlock(machineCodeBlock); inlinedCaller->setScopeChain(calleeAsFunction->scope()); if (nextInlineCallFrame) - inlinedCaller->setCallerFrame(machineCaller + nextInlineCallFrame->stackOffset); + inlinedCaller->setCallerFrame(this + nextInlineCallFrame->stackOffset); else - inlinedCaller->setCallerFrame(machineCaller); + inlinedCaller->setCallerFrame(this); inlinedCaller->setInlineCallFrame(inlineCallFrame); inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->arguments.size()); @@ -116,7 +129,34 @@ CallFrame* CallFrame::trueCallerFrame() inlineCallFrame = nextInlineCallFrame; } - return machineCaller + codeOrigin.inlineCallFrame->stackOffset; + return this + codeOrigin.inlineCallFrame->stackOffset; +} + +CallFrame* CallFrame::trueCallerFrame() +{ + // this -> The callee; this is either an inlined callee in which case it already has + // a pointer to the true caller. Otherwise it contains current PC in the machine + // caller. + // + // machineCaller -> The caller according to the machine, which may be zero or + // more frames above the true caller due to inlining. + + // Am I an inline call frame? If so, we're done. + if (isInlineCallFrame()) + return callerFrame(); + + // I am a machine call frame, so the question is: is my caller a machine call frame + // that has inlines or a machine call frame that doesn't? + CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag(); + if (!machineCaller) + return 0; + ASSERT(!machineCaller->isInlineCallFrame()); + + // Figure out how we want to get the current code location. + if (hasHostCallFrameFlag() || returnAddressIsInCtiTrampoline(returnPC())) + return machineCaller->trueCallFrameFromVMCode(); + + return machineCaller->trueCallFrame(returnPC()); } #endif diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index d5037b794..e0a291f8b 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.h +++ b/Source/JavaScriptCore/interpreter/CallFrame.h @@ -23,6 +23,7 @@ #ifndef CallFrame_h #define CallFrame_h +#include "AbstractPC.h" #include "JSGlobalData.h" #include "MacroAssemblerCodeRef.h" #include "RegisterFile.h" @@ -104,8 +105,10 @@ namespace JSC { #if ENABLE(JIT) ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); } #endif + AbstractPC abstractReturnPC(JSGlobalData& globalData) { return AbstractPC(globalData, this); } #if ENABLE(DFG_JIT) InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].asInlineCallFrame(); } + unsigned codeOriginIndexForDFGWithInlining() const { return this[RegisterFile::ArgumentCount].tag(); } #else // This will never be called if !ENABLE(DFG_JIT) since all calls should be guarded by // isInlineCallFrame(). But to make it easier to write code without having a bunch of @@ -185,14 +188,30 @@ namespace JSC { void setInlineCallFrame(InlineCallFrame* inlineCallFrame) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = inlineCallFrame; } - // Call this to get the semantically correct JS CallFrame*. This resolves issues - // surrounding inlining and the HostCallFrameFlag stuff. + // Call this to get the semantically correct JS CallFrame* for the + // currently executing function. + CallFrame* trueCallFrame(AbstractPC); + + // Call this to get the semantically correct JS CallFrame* corresponding + // to the caller. This resolves issues surrounding inlining and the + // HostCallFrameFlag stuff. CallFrame* trueCallerFrame(); #else bool isInlineCallFrame() { return false; } + CallFrame* trueCallFrame(AbstractPC) { return this; } CallFrame* trueCallerFrame() { return callerFrame()->removeHostCallFrameFlag(); } #endif + + // Call this to get the true call frame (accounted for inlining and any + // other optimizations), when you have entered into VM code through one + // of the "blessed" entrypoints (JITStubs or DFGOperations). This means + // that if you're pretty much anywhere in the VM you can safely call this; + // though if you were to magically get an ExecState* by, say, interrupting + // a thread that is running JS code and brutishly scraped the call frame + // register, calling this method would probably lead to horrible things + // happening. + CallFrame* trueCallFrameFromVMCode() { return trueCallFrame(AbstractPC()); } private: static const intptr_t HostCallFrameFlag = 1; diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index 980bf8a1a..51843f2d2 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -905,7 +905,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S PutPropertySlot slot; globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot); } else - globalObject->methodTable()->putWithAttributes(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete); + globalObject->methodTable()->putDirectVirtual(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete); // var declarations return undefined result = jsUndefined(); continue; @@ -1324,7 +1324,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue JSObject* variableObject; for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) { ASSERT(node); - if (node->object->isVariableObject()) { + if (node->object->isVariableObject() && !node->object->isStaticScopeObject()) { variableObject = static_cast<JSVariableObject*>(node->object.get()); break; } @@ -2579,7 +2579,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (propName.getUInt32(i)) callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i)); else { - Identifier property(callFrame, propName.toString(callFrame)); + Identifier property(callFrame, propName.toString(callFrame)->value(callFrame)); CHECK_FOR_EXCEPTION(); callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property)); } @@ -3310,9 +3310,10 @@ skip_id_custom_self: JSValue baseValue = callFrame->r(base).jsValue(); Identifier& ident = codeBlock->identifier(property); PutPropertySlot slot(codeBlock->isStrictMode()); - if (direct) - baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot); - else + if (direct) { + ASSERT(baseValue.isObject()); + asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot); + } else baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot); CHECK_FOR_EXCEPTION(); @@ -3428,9 +3429,10 @@ skip_id_custom_self: JSValue baseValue = callFrame->r(base).jsValue(); Identifier& ident = codeBlock->identifier(property); PutPropertySlot slot(codeBlock->isStrictMode()); - if (direct) - baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot); - else + if (direct) { + ASSERT(baseValue.isObject()); + asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot); + } else baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot); CHECK_FOR_EXCEPTION(); @@ -3482,7 +3484,7 @@ skip_id_custom_self: NEXT_INSTRUCTION(); } { - Identifier propertyName(callFrame, subscript.toString(callFrame)); + Identifier propertyName(callFrame, subscript.toString(callFrame)->value(callFrame)); result = baseValue.get(callFrame, propertyName); } CHECK_FOR_EXCEPTION(); @@ -3557,7 +3559,7 @@ skip_id_custom_self: else result = baseValue.get(callFrame, i); } else { - Identifier property(callFrame, subscript.toString(callFrame)); + Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); result = baseValue.get(callFrame, property); } @@ -3604,7 +3606,7 @@ skip_id_custom_self: } else baseValue.put(callFrame, i, callFrame->r(value).jsValue()); } else { - Identifier property(callFrame, subscript.toString(callFrame)); + Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); if (!globalData->exception) { // Don't put to an object if toString threw an exception. PutPropertySlot slot(codeBlock->isStrictMode()); baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot); @@ -3636,7 +3638,7 @@ skip_id_custom_self: result = baseObj->methodTable()->deletePropertyByIndex(baseObj, callFrame, i); else { CHECK_FOR_EXCEPTION(); - Identifier property(callFrame, subscript.toString(callFrame)); + Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); CHECK_FOR_EXCEPTION(); result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, property); } @@ -4943,7 +4945,7 @@ skip_id_custom_self: original constructor, using constant message as the message string. The result is thrown. */ - UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame); + UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame)->value(callFrame); exceptionValue = JSValue(createReferenceError(callFrame, message)); goto vm_throw; } @@ -4957,52 +4959,41 @@ skip_id_custom_self: int result = vPC[1].u.operand; return callFrame->r(result).jsValue(); } - DEFINE_OPCODE(op_put_getter) { - /* put_getter base(r) property(id) function(r) + DEFINE_OPCODE(op_put_getter_setter) { + /* put_getter_setter base(r) property(id) getter(r) setter(r) - Sets register function on register base as the getter named - by identifier property. Base and function are assumed to be - objects as this op should only be used for getters defined - in object literal form. + Puts accessor descriptor to register base as the named + identifier property. Base and function may be objects + or undefined, this op should only be used for accessors + defined in object literal form. Unlike many opcodes, this one does not write any output to the register file. */ int base = vPC[1].u.operand; int property = vPC[2].u.operand; - int function = vPC[3].u.operand; + int getterReg = vPC[3].u.operand; + int setterReg = vPC[4].u.operand; ASSERT(callFrame->r(base).jsValue().isObject()); JSObject* baseObj = asObject(callFrame->r(base).jsValue()); Identifier& ident = codeBlock->identifier(property); - ASSERT(callFrame->r(function).jsValue().isObject()); - baseObj->methodTable()->defineGetter(baseObj, callFrame, ident, asObject(callFrame->r(function).jsValue()), 0); - vPC += OPCODE_LENGTH(op_put_getter); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_put_setter) { - /* put_setter base(r) property(id) function(r) + GetterSetter* accessor = GetterSetter::create(callFrame); - Sets register function on register base as the setter named - by identifier property. Base and function are assumed to be - objects as this op should only be used for setters defined - in object literal form. + JSValue getter = callFrame->r(getterReg).jsValue(); + JSValue setter = callFrame->r(setterReg).jsValue(); + ASSERT(getter.isObject() || getter.isUndefined()); + ASSERT(setter.isObject() || setter.isUndefined()); + ASSERT(getter.isObject() || setter.isObject()); - Unlike many opcodes, this one does not write any output to - the register file. - */ - int base = vPC[1].u.operand; - int property = vPC[2].u.operand; - int function = vPC[3].u.operand; - - ASSERT(callFrame->r(base).jsValue().isObject()); - JSObject* baseObj = asObject(callFrame->r(base).jsValue()); - Identifier& ident = codeBlock->identifier(property); - ASSERT(callFrame->r(function).jsValue().isObject()); - baseObj->methodTable()->defineSetter(baseObj, callFrame, ident, asObject(callFrame->r(function).jsValue()), 0); + if (!getter.isUndefined()) + accessor->setGetter(callFrame->globalData(), asObject(getter)); + if (!setter.isUndefined()) + accessor->setSetter(callFrame->globalData(), asObject(setter)); + baseObj->putDirectAccessor(callFrame->globalData(), ident, accessor, Accessor); - vPC += OPCODE_LENGTH(op_put_setter); + vPC += OPCODE_LENGTH(op_put_getter_setter); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_method_check) { @@ -5106,9 +5097,9 @@ skip_id_custom_self: #endif // ENABLE(INTERPRETER) } -JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const +JSValue Interpreter::retrieveArgumentsFromVMCode(CallFrame* callFrame, JSFunction* function) const { - CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function); + CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function); if (!functionCallFrame) return jsNull(); @@ -5130,9 +5121,9 @@ JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* functio return JSValue(arguments); } -JSValue Interpreter::retrieveCaller(CallFrame* callFrame, JSFunction* function) const +JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const { - CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function); + CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function); if (!functionCallFrame) return jsNull(); @@ -5177,9 +5168,9 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp function = callerFrame->callee(); } -CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, JSFunction* function) +CallFrame* Interpreter::findFunctionCallFrameFromVMCode(CallFrame* callFrame, JSFunction* function) { - for (CallFrame* candidate = callFrame; candidate; candidate = candidate->trueCallerFrame()) { + for (CallFrame* candidate = callFrame->trueCallFrameFromVMCode(); candidate; candidate = candidate->trueCallerFrame()) { if (candidate->callee() == function) return candidate; } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h index 6dfd331f8..1943513ae 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.h +++ b/Source/JavaScriptCore/interpreter/Interpreter.h @@ -79,6 +79,16 @@ namespace JSC { JSGlobalData& globalData; CallFrame* oldCallFrame; }; + + class NativeCallFrameTracer { + public: + ALWAYS_INLINE NativeCallFrameTracer(JSGlobalData* global, CallFrame* callFrame) + { + ASSERT(global); + ASSERT(callFrame); + global->topCallFrame = callFrame; + } + }; #if PLATFORM(IOS) // We use a smaller reentrancy limit on iPhone because of the high amount of @@ -131,8 +141,8 @@ namespace JSC { JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, ScopeChainNode*); JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, ScopeChainNode*, int globalRegisterOffset); - JSValue retrieveArguments(CallFrame*, JSFunction*) const; - JS_EXPORT_PRIVATE JSValue retrieveCaller(CallFrame*, JSFunction*) const; + JSValue retrieveArgumentsFromVMCode(CallFrame*, JSFunction*) const; + JS_EXPORT_PRIVATE JSValue retrieveCallerFromVMCode(CallFrame*, JSFunction*) const; JS_EXPORT_PRIVATE void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const; void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); @@ -172,7 +182,7 @@ namespace JSC { static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc); - static CallFrame* findFunctionCallFrame(CallFrame*, JSFunction*); + static CallFrame* findFunctionCallFrameFromVMCode(CallFrame*, JSFunction*); JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*); |