diff options
author | Kristian Monsen <kristianm@google.com> | 2010-05-21 16:53:46 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-05-25 10:24:15 +0100 |
commit | 6c2af9490927c3c5959b5cb07461b646f8b32f6c (patch) | |
tree | f7111b9b22befab472616c1d50ec94eb50f1ec8c /JavaScriptCore/interpreter | |
parent | a149172322a9067c14e8b474a53e63649aa17cad (diff) | |
download | external_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.zip external_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.tar.gz external_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.tar.bz2 |
Merge WebKit at r59636: Initial merge by git
Change-Id: I59b289c4e6b18425f06ce41cc9d34c522515de91
Diffstat (limited to 'JavaScriptCore/interpreter')
-rw-r--r-- | JavaScriptCore/interpreter/Interpreter.cpp | 194 | ||||
-rw-r--r-- | JavaScriptCore/interpreter/Interpreter.h | 4 |
2 files changed, 181 insertions, 17 deletions
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index e53f236..7548cf9 100644 --- a/JavaScriptCore/interpreter/Interpreter.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -191,6 +191,76 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* return false; } +NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) +{ + int dst = vPC[1].u.operand; + JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(vPC[2].u.jsCell); + ASSERT(globalObject->isGlobalObject()); + int property = vPC[3].u.operand; + Structure* structure = vPC[4].u.structure; + int offset = vPC[5].u.operand; + CodeBlock* codeBlock = callFrame->codeBlock(); + int skip = vPC[6].u.operand + codeBlock->needsFullScopeChain(); + + ScopeChainNode* scopeChain = callFrame->scopeChain(); + ScopeChainIterator iter = scopeChain->begin(); + ScopeChainIterator end = scopeChain->end(); + ASSERT(iter != end); + while (skip--) { + JSObject* o = *iter; + if (o->hasCustomProperties()) { + Identifier& ident = codeBlock->identifier(property); + do { + PropertySlot slot(o); + if (o->getPropertySlot(callFrame, ident, slot)) { + JSValue result = slot.getValue(callFrame, ident); + exceptionValue = callFrame->globalData().exception; + if (exceptionValue) + return false; + callFrame->r(dst) = JSValue(result); + return true; + } + if (iter == end) + break; + o = *iter; + ++iter; + } while (true); + exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock); + return false; + } + ++iter; + } + + if (structure == globalObject->structure()) { + callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset)); + return true; + } + + Identifier& ident = codeBlock->identifier(property); + PropertySlot slot(globalObject); + if (globalObject->getPropertySlot(callFrame, ident, slot)) { + JSValue result = slot.getValue(callFrame, ident); + if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) { + if (vPC[4].u.structure) + vPC[4].u.structure->deref(); + globalObject->structure()->ref(); + vPC[4] = globalObject->structure(); + vPC[5] = slot.cachedOffset(); + callFrame->r(dst) = JSValue(result); + return true; + } + + exceptionValue = callFrame->globalData().exception; + if (exceptionValue) + return false; + callFrame->r(dst) = JSValue(result); + return true; + } + + exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock); + return false; +} + NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC) { int dst = vPC[1].u.operand; @@ -637,7 +707,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S return result; } -JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception) +JSValue Interpreter::executeCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception) { ASSERT(!scopeChain->globalData->exception); @@ -665,7 +735,7 @@ JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* for (ArgList::const_iterator it = args.begin(); it != end; ++it) newCallFrame->r(++dst) = *it; - CodeBlock* codeBlock = &functionExecutable->bytecode(callFrame, scopeChain); + CodeBlock* codeBlock = &functionExecutable->bytecodeForCall(callFrame, scopeChain); newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); if (UNLIKELY(!newCallFrame)) { *exception = createStackOverflowError(callFrame); @@ -685,7 +755,69 @@ JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* m_reentryDepth++; #if ENABLE(JIT) - result = functionExecutable->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = functionExecutable->jitCodeForCall(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); +#else + result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); +#endif + m_reentryDepth--; + } + + if (*profiler) + (*profiler)->didExecute(callFrame, function); + + m_registerFile.shrink(oldEnd); + return result; +} + +JSValue Interpreter::executeConstruct(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception) +{ + ASSERT(!scopeChain->globalData->exception); + + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { + *exception = createStackOverflowError(callFrame); + return jsNull(); + } + } + + Register* oldEnd = m_registerFile.end(); + int argc = 1 + args.size(); // implicit "this" parameter + + if (!m_registerFile.grow(oldEnd + argc)) { + *exception = createStackOverflowError(callFrame); + return jsNull(); + } + + DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject); + + CallFrame* newCallFrame = CallFrame::create(oldEnd); + size_t dst = 0; + newCallFrame->r(0) = JSValue(thisObj); + ArgList::const_iterator end = args.end(); + for (ArgList::const_iterator it = args.begin(); it != end; ++it) + newCallFrame->r(++dst) = *it; + + CodeBlock* codeBlock = &functionExecutable->bytecodeForConstruct(callFrame, scopeChain); + newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); + if (UNLIKELY(!newCallFrame)) { + *exception = createStackOverflowError(callFrame); + m_registerFile.shrink(oldEnd); + return jsNull(); + } + // a 0 codeBlock indicates a built-in caller + newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function); + + Profiler** profiler = Profiler::enabledProfilerReference(); + if (*profiler) + (*profiler)->willExecute(callFrame, function); + + JSValue result; + { + SamplingTool::CallRecord callRecord(m_sampler.get()); + + m_reentryDepth++; +#if ENABLE(JIT) + result = functionExecutable->jitCodeForConstruct(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -723,7 +855,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE for (int i = 0; i < argc; ++i) newCallFrame->r(++dst) = jsUndefined(); - CodeBlock* codeBlock = &FunctionExecutable->bytecode(callFrame, scopeChain); + CodeBlock* codeBlock = &FunctionExecutable->bytecodeForCall(callFrame, scopeChain); newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); if (UNLIKELY(!newCallFrame)) { *exception = createStackOverflowError(callFrame); @@ -733,7 +865,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE // a 0 codeBlock indicates a built-in caller newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function); #if ENABLE(JIT) - FunctionExecutable->jitCode(newCallFrame, scopeChain); + FunctionExecutable->jitCodeForCall(newCallFrame, scopeChain); #endif CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc }; @@ -753,7 +885,7 @@ JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception) m_reentryDepth++; #if ENABLE(JIT) - result = closure.functionExecutable->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception); + result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception); #else result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception); #endif @@ -799,11 +931,12 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec } } - { // Scope for BatchedTransitionOptimizer - + unsigned numVariables = codeBlock->numVariables(); + int numFunctions = codeBlock->numberOfFunctionDecls(); + if (numVariables || numFunctions) { + // Scope for BatchedTransitionOptimizer BatchedTransitionOptimizer optimizer(variableObject); - unsigned numVariables = codeBlock->numVariables(); for (unsigned i = 0; i < numVariables; ++i) { const Identifier& ident = codeBlock->variable(i); if (!variableObject->hasProperty(callFrame, ident)) { @@ -812,13 +945,11 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec } } - int numFunctions = codeBlock->numberOfFunctionDecls(); for (int i = 0; i < numFunctions; ++i) { FunctionExecutable* function = codeBlock->functionDecl(i); PutPropertySlot slot; variableObject->put(callFrame, function->name(), function->make(callFrame, scopeChain), slot); } - } Register* oldEnd = m_registerFile.end(); @@ -1237,6 +1368,20 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi vPC += OPCODE_LENGTH(op_new_array); NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_new_regexp) { + /* new_regexp dst(r) regExp(re) + + Constructs a new RegExp instance using the original + constructor from regexp regExp, and puts the result in + register dst. + */ + int dst = vPC[1].u.operand; + int regExp = vPC[2].u.operand; + callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject->regExpStructure(), callFrame->codeBlock()->regexp(regExp))); + + vPC += OPCODE_LENGTH(op_new_regexp); + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_mov) { /* mov dst(r) src(r) @@ -1989,6 +2134,24 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_resolve_global_dynamic) { + /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n), depth(n) + + Performs a dynamic property lookup for the given property, on the provided + global object. If structure matches the Structure of the global then perform + a fast lookup using the case offset, otherwise fall back to a full resolve and + cache the new structure and offset. + + This walks through n levels of the scope chain to verify that none of those levels + in the scope chain include dynamically added properties. + */ + if (UNLIKELY(!resolveGlobalDynamic(callFrame, vPC, exceptionValue))) + goto vm_throw; + + vPC += OPCODE_LENGTH(op_resolve_global_dynamic); + + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_get_global_var) { /* get_global_var dst(r) globalObject(c) index(n) @@ -2016,7 +2179,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi scope->registerAt(index) = JSValue(callFrame->r(value).jsValue()); vPC += OPCODE_LENGTH(op_put_global_var); NEXT_INSTRUCTION(); - } + } DEFINE_OPCODE(op_get_scoped_var) { /* get_scoped_var dst(r) index(n) skip(n) @@ -2035,7 +2198,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ++iter; ASSERT(iter != end); } - ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); callFrame->r(dst) = scope->registerAt(index); @@ -3407,7 +3569,7 @@ skip_id_custom_self: if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; - CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain); + CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); CallFrame* previousCallFrame = callFrame; @@ -3561,7 +3723,7 @@ skip_id_custom_self: if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; - CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain); + CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); CallFrame* previousCallFrame = callFrame; @@ -3809,7 +3971,7 @@ skip_id_custom_self: if (constructType == ConstructTypeJS) { ScopeChainNode* callDataScopeChain = constructData.js.scopeChain; - CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecode(callFrame, callDataScopeChain); + CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecodeForConstruct(callFrame, callDataScopeChain); Structure* structure; JSValue prototype = callFrame->r(proto).jsValue(); diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h index cf8b342..0a5d592 100644 --- a/JavaScriptCore/interpreter/Interpreter.h +++ b/JavaScriptCore/interpreter/Interpreter.h @@ -96,7 +96,8 @@ namespace JSC { bool isOpcode(Opcode); JSValue execute(ProgramExecutable*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception); - JSValue execute(FunctionExecutable*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception); + JSValue executeCall(FunctionExecutable*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception); + JSValue executeConstruct(FunctionExecutable*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception); JSValue execute(EvalExecutable* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception); JSValue retrieveArguments(CallFrame*, JSFunction*) const; @@ -127,6 +128,7 @@ namespace JSC { NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue); NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue& exceptionValue); NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue); + NEVER_INLINE bool resolveGlobalDynamic(CallFrame*, Instruction*, JSValue& exceptionValue); NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC); NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue); NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC); |