summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/interpreter')
-rw-r--r--JavaScriptCore/interpreter/CallFrame.h5
-rw-r--r--JavaScriptCore/interpreter/Interpreter.cpp273
-rw-r--r--JavaScriptCore/interpreter/Interpreter.h10
3 files changed, 187 insertions, 101 deletions
diff --git a/JavaScriptCore/interpreter/CallFrame.h b/JavaScriptCore/interpreter/CallFrame.h
index 7ea59fb..bde9786 100644
--- a/JavaScriptCore/interpreter/CallFrame.h
+++ b/JavaScriptCore/interpreter/CallFrame.h
@@ -106,8 +106,9 @@ namespace JSC {
CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
#if ENABLE(JIT)
ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
-#else
- Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
+#endif
+#if ENABLE(INTERPRETER)
+ Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
#endif
void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 8160249..26f7a6b 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -79,7 +79,7 @@ static int depth(CodeBlock* codeBlock, ScopeChain& sc)
return sc.localDepth();
}
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int dst = vPC[1].u.operand;
@@ -294,7 +294,7 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst
return false;
}
-#endif // !ENABLE(JIT)
+#endif // ENABLE(INTERPRETER)
ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
{
@@ -333,7 +333,7 @@ ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newC
return CallFrame::create(r);
}
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
{
if (value.isObject())
@@ -384,12 +384,12 @@ Interpreter::Interpreter()
: m_sampleEntryDepth(0)
, m_reentryDepth(0)
{
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
privateExecute(InitializeAndReturn, 0, 0, 0);
for (int i = 0; i < numOpcodeIDs; ++i)
m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
-#endif // HAVE(COMPUTED_GOTO)
+#endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
#if ENABLE(OPCODE_SAMPLING)
enableSampler();
@@ -497,7 +497,7 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
bool Interpreter::isOpcode(Opcode opcode)
{
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
return opcode != HashTraits<Opcode>::emptyValue()
&& !HashTraits<Opcode>::isDeletedValue(opcode)
&& m_opcodeIDTable.contains(opcode);
@@ -547,7 +547,18 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
return false;
codeBlock = callerFrame->codeBlock();
- bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+ if (callerFrame->globalData().canUseJIT())
+#endif
+ bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#if ENABLE(INTERPRETER)
+ else
+ bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
+#endif
+#else
+ bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
+#endif
callFrame = callerFrame;
return true;
}
@@ -594,16 +605,24 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
// the profiler manually that the call instruction has returned, since
// we'll never reach the relevant op_profile_did_call.
if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
-#if !ENABLE(JIT)
- // FIXME: Why 8? - work out what this magic value is, replace the constant with something more helpful.
- if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
- profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 1].u.operand).jsValue());
- else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
- profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 9].u.operand).jsValue());
-#else
- int functionRegisterIndex;
- if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
- profiler->didExecute(callFrame, callFrame->r(functionRegisterIndex).jsValue());
+#if ENABLE(INTERPRETER)
+ if (!callFrame->globalData().canUseJIT()) {
+ // FIXME: Why 8? - work out what this magic value is, replace the constant with something more helpful.
+ if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
+ profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 1].u.operand).jsValue());
+ else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
+ profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 9].u.operand).jsValue());
+ }
+#if ENABLE(JIT)
+ else
+#endif
+#endif
+#if ENABLE(JIT)
+ {
+ int functionRegisterIndex;
+ if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
+ profiler->didExecute(callFrame, callFrame->r(functionRegisterIndex).jsValue());
+ }
#endif
}
@@ -676,12 +695,20 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
{
SamplingTool::CallRecord callRecord(m_sampler.get());
- m_reentryDepth++;
+ m_reentryDepth++;
#if ENABLE(JIT)
- result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
-#else
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
#endif
+ result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
+
m_reentryDepth--;
}
@@ -749,12 +776,19 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
{
SamplingTool::CallRecord callRecord(m_sampler.get());
- m_reentryDepth++;
- #if ENABLE(JIT)
- result = callData.js.functionExecutable->jitCodeForCall(newCallFrame, callDataScopeChain).execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData, exception);
- #else
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
- #endif
+ m_reentryDepth++;
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
+#endif
+ result = callData.js.functionExecutable->jitCodeForCall(newCallFrame, callDataScopeChain).execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
m_reentryDepth--;
}
@@ -841,12 +875,19 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
{
SamplingTool::CallRecord callRecord(m_sampler.get());
- m_reentryDepth++;
- #if ENABLE(JIT)
- result = constructData.js.functionExecutable->jitCodeForConstruct(newCallFrame, constructDataScopeChain).execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData, exception);
- #else
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
- #endif
+ m_reentryDepth++;
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
+#endif
+ result = constructData.js.functionExecutable->jitCodeForConstruct(newCallFrame, constructDataScopeChain).execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
m_reentryDepth--;
}
@@ -922,11 +963,13 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE
return CallFrameClosure();
}
// a 0 codeBlock indicates a built-in caller
- newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);
+ newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);
#if ENABLE(JIT)
- FunctionExecutable->jitCodeForCall(newCallFrame, scopeChain);
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
+#endif
+ FunctionExecutable->jitCodeForCall(newCallFrame, scopeChain);
#endif
-
CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
return result;
}
@@ -942,11 +985,18 @@ JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception)
{
SamplingTool::CallRecord callRecord(m_sampler.get());
- m_reentryDepth++;
+ m_reentryDepth++;
#if ENABLE(JIT)
- result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
-#else
- result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
+#if ENABLE(INTERPRETER)
+ if (closure.newCallFrame->globalData().canUseJIT())
+#endif
+ result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
#endif
m_reentryDepth--;
}
@@ -1041,10 +1091,18 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
SamplingTool::CallRecord callRecord(m_sampler.get());
m_reentryDepth++;
+
#if ENABLE(JIT)
- result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
-#else
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
+#endif
+ result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
m_reentryDepth--;
}
@@ -1084,7 +1142,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook
}
}
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
{
int dst = vPC[1].u.operand;
@@ -1320,28 +1378,32 @@ NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction*
vPC[4] = 0;
}
-#endif // !ENABLE(JIT)
+#endif // ENABLE(INTERPRETER)
JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* exception)
{
// One-time initialization of our address tables. We have to put this code
// here because our labels are only in scope inside this function.
if (UNLIKELY(flag == InitializeAndReturn)) {
- #if HAVE(COMPUTED_GOTO)
+ #if ENABLE(COMPUTED_GOTO_INTERPRETER)
#define LIST_OPCODE_LABEL(id, length) &&id,
static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
for (size_t i = 0; i < sizeof(labels) / sizeof(Opcode); ++i)
m_opcodeTable[i] = labels[i];
#undef LIST_OPCODE_LABEL
- #endif // HAVE(COMPUTED_GOTO)
+ #endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
return JSValue();
}
-
+
#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
// Mixing Interpreter + JIT is not supported.
- ASSERT_NOT_REACHED();
+ if (callFrame->globalData().canUseJIT())
+#endif
+ ASSERT_NOT_REACHED();
#endif
-#if !!ENABLE(JIT)
+
+#if !ENABLE(INTERPRETER)
UNUSED_PARAM(registerFile);
UNUSED_PARAM(callFrame);
UNUSED_PARAM(exception);
@@ -1385,7 +1447,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
#define SAMPLE(codeBlock, vPC)
#endif
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
#define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
#if ENABLE(OPCODE_STATS)
#define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
@@ -2417,7 +2479,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_getter_proto);
#endif
DEFINE_OPCODE(op_get_by_id_getter_proto) {
@@ -2459,10 +2521,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_getter_proto:
#endif
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_custom_proto);
#endif
DEFINE_OPCODE(op_get_by_id_custom_proto) {
@@ -2501,7 +2563,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_custom_proto:
#endif
DEFINE_OPCODE(op_get_by_id_self_list) {
@@ -2592,7 +2654,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_getter_self);
#endif
DEFINE_OPCODE(op_get_by_id_getter_self) {
@@ -2632,10 +2694,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_getter_self:
#endif
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_custom_self);
#endif
DEFINE_OPCODE(op_get_by_id_custom_self) {
@@ -2669,7 +2731,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_custom_self:
#endif
DEFINE_OPCODE(op_get_by_id_generic) {
@@ -2692,7 +2754,7 @@ skip_id_custom_self:
vPC += OPCODE_LENGTH(op_get_by_id_generic);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_getter_chain);
#endif
DEFINE_OPCODE(op_get_by_id_getter_chain) {
@@ -2744,10 +2806,10 @@ skip_id_custom_self:
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_getter_chain:
#endif
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_custom_chain);
#endif
DEFINE_OPCODE(op_get_by_id_custom_chain) {
@@ -2796,7 +2858,7 @@ skip_id_custom_self:
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_custom_chain:
#endif
DEFINE_OPCODE(op_get_array_length) {
@@ -2840,23 +2902,31 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_put_by_id) {
- /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
+ /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
Generic property access: Sets the property named by identifier
property, belonging to register base, to register value.
Unlike many opcodes, this one does not write any output to
the register file.
+
+ The "direct" flag should only be set this put_by_id is to initialize
+ an object literal.
*/
int base = vPC[1].u.operand;
int property = vPC[2].u.operand;
int value = vPC[3].u.operand;
+ int direct = vPC[8].u.operand;
JSValue baseValue = callFrame->r(base).jsValue();
Identifier& ident = codeBlock->identifier(property);
PutPropertySlot slot;
- baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
+ if (direct) {
+ baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
+ ASSERT(slot.base() == baseValue);
+ } else
+ baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
CHECK_FOR_EXCEPTION();
tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
@@ -2865,7 +2935,7 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_put_by_id_transition) {
- /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n)
+ /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
Cached property access: Attempts to set a new property with a cached transition
property named by identifier property, belonging to register base,
@@ -2886,19 +2956,21 @@ skip_id_custom_self:
if (LIKELY(baseCell->structure() == oldStructure)) {
ASSERT(baseCell->isObject());
JSObject* baseObject = asObject(baseCell);
-
- RefPtr<Structure>* it = vPC[6].u.structureChain->head();
-
- JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
- while (!proto.isNull()) {
- if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
- uncachePutByID(codeBlock, vPC);
- NEXT_INSTRUCTION();
+ int direct = vPC[8].u.operand;
+
+ if (direct) {
+ RefPtr<Structure>* it = vPC[6].u.structureChain->head();
+
+ JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
+ while (!proto.isNull()) {
+ if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
+ uncachePutByID(codeBlock, vPC);
+ NEXT_INSTRUCTION();
+ }
+ ++it;
+ proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
}
- ++it;
- proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
}
-
baseObject->transitionTo(newStructure);
int value = vPC[3].u.operand;
@@ -2915,7 +2987,7 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_put_by_id_replace) {
- /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n)
+ /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n) direct(b)
Cached property access: Attempts to set a pre-existing, cached
property named by identifier property, belonging to register base,
@@ -2950,7 +3022,7 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_put_by_id_generic) {
- /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
+ /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
Generic property access: Sets the property named by identifier
property, belonging to register base, to register value.
@@ -2961,11 +3033,16 @@ skip_id_custom_self:
int base = vPC[1].u.operand;
int property = vPC[2].u.operand;
int value = vPC[3].u.operand;
+ int direct = vPC[8].u.operand;
JSValue baseValue = callFrame->r(base).jsValue();
Identifier& ident = codeBlock->identifier(property);
PutPropertySlot slot;
- baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
+ if (direct) {
+ baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
+ ASSERT(slot.base() == baseValue);
+ } else
+ baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
CHECK_FOR_EXCEPTION();
vPC += OPCODE_LENGTH(op_put_by_id_generic);
@@ -3704,17 +3781,17 @@ skip_id_custom_self:
goto vm_throw;
}
ASSERT(!asFunction(callFrame->callee())->isHostFunction());
- uint32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
- uint32_t inplaceArgs = min(argCount, expectedParams);
- uint32_t i = 0;
+ int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
+ int32_t inplaceArgs = min(static_cast<int32_t>(argCount), expectedParams);
+ int32_t i = 0;
Register* argStore = callFrame->registers() + argsOffset;
// First step is to copy the "expected" parameters from their normal location relative to the callframe
for (; i < inplaceArgs; i++)
argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
// Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
- for (; i < argCount; i++)
- argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - argCount - 1];
+ for (; i < static_cast<int32_t>(argCount); i++)
+ argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - static_cast<int32_t>(argCount) - 1];
} else if (!arguments.isUndefinedOrNull()) {
if (!arguments.isObject()) {
exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - codeBlock->instructions().begin(), codeBlock);
@@ -3907,7 +3984,7 @@ skip_id_custom_self:
JSValue returnValue = callFrame->r(result).jsValue();
- vPC = callFrame->returnPC();
+ vPC = callFrame->returnVPC();
callFrame = callFrame->callerFrame();
if (callFrame->hasHostCallFrameFlag())
@@ -3951,7 +4028,7 @@ skip_id_custom_self:
if (UNLIKELY(!returnValue.isObject()))
returnValue = callFrame->r(vPC[2].u.operand).jsValue();
- vPC = callFrame->returnPC();
+ vPC = callFrame->returnVPC();
callFrame = callFrame->callerFrame();
if (callFrame->hasHostCallFrameFlag())
@@ -4136,7 +4213,6 @@ skip_id_custom_self:
callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
codeBlock = newCodeBlock;
vPC = newCodeBlock->instructions().begin();
-
#if ENABLE(OPCODE_STATS)
OpcodeStats::resetLastInstruction();
#endif
@@ -4299,7 +4375,7 @@ skip_id_custom_self:
vPC += target;
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
// Appease GCC
goto *(&&skip_new_scope);
#endif
@@ -4315,7 +4391,7 @@ skip_id_custom_self:
vPC += OPCODE_LENGTH(op_push_new_scope);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_new_scope:
#endif
DEFINE_OPCODE(op_catch) {
@@ -4529,14 +4605,14 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
}
-#if !HAVE(COMPUTED_GOTO)
+#if !ENABLE(COMPUTED_GOTO_INTERPRETER)
} // iterator loop ends
#endif
#undef NEXT_INSTRUCTION
#undef DEFINE_OPCODE
#undef CHECK_FOR_EXCEPTION
#undef CHECK_FOR_TIMEOUT
-#endif // !ENABLE(JIT)
+#endif // ENABLE(INTERPRETER)
}
JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
@@ -4592,8 +4668,17 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp
CodeBlock* callerCodeBlock = callerFrame->codeBlock();
if (!callerCodeBlock)
return;
-
- unsigned bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+ unsigned bytecodeOffset = 0;
+#if ENABLE(INTERPRETER)
+ if (!callerFrame->globalData().canUseJIT())
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
+#if ENABLE(JIT)
+ else
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#endif
+#else
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#endif
lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
sourceID = callerCodeBlock->ownerExecutable()->sourceID();
sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h
index 555bbf9..50f07b3 100644
--- a/JavaScriptCore/interpreter/Interpreter.h
+++ b/JavaScriptCore/interpreter/Interpreter.h
@@ -75,7 +75,7 @@ namespace JSC {
Opcode getOpcode(OpcodeID id)
{
- #if HAVE(COMPUTED_GOTO)
+ #if ENABLE(COMPUTED_GOTO_INTERPRETER)
return m_opcodeTable[id];
#else
return id;
@@ -84,7 +84,7 @@ namespace JSC {
OpcodeID getOpcodeID(Opcode opcode)
{
- #if HAVE(COMPUTED_GOTO)
+ #if ENABLE(COMPUTED_GOTO_INTERPRETER)
ASSERT(isOpcode(opcode));
return m_opcodeIDTable.get(opcode);
#else
@@ -123,7 +123,7 @@ namespace JSC {
JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue& exceptionValue);
NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue);
@@ -136,7 +136,7 @@ namespace JSC {
void uncacheGetByID(CodeBlock*, Instruction* vPC);
void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const PutPropertySlot&);
void uncachePutByID(CodeBlock*, Instruction* vPC);
-#endif // !ENABLE(JIT)
+#endif // ENABLE(INTERPRETER)
NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&);
@@ -159,7 +159,7 @@ namespace JSC {
RegisterFile m_registerFile;
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
#endif