diff options
| author | Steve Block <steveblock@google.com> | 2010-04-27 16:31:00 +0100 |
|---|---|---|
| committer | Steve Block <steveblock@google.com> | 2010-05-11 14:42:12 +0100 |
| commit | dcc8cf2e65d1aa555cce12431a16547e66b469ee (patch) | |
| tree | 92a8d65cd5383bca9749f5327fb5e440563926e6 /JavaScriptCore/interpreter | |
| parent | ccac38a6b48843126402088a309597e682f40fe6 (diff) | |
| download | external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2 | |
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'JavaScriptCore/interpreter')
| -rw-r--r-- | JavaScriptCore/interpreter/Interpreter.cpp | 239 | ||||
| -rw-r--r-- | JavaScriptCore/interpreter/Interpreter.h | 2 |
2 files changed, 205 insertions, 36 deletions
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index 6dbbcf9..40f6458 100644 --- a/JavaScriptCore/interpreter/Interpreter.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -522,8 +522,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerExecutable()->sourceID()), ReadOnly | DontDelete); exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerExecutable()->sourceURL()), ReadOnly | DontDelete); } - - if (exception->isWatchdogException()) { + + ComplType exceptionType = exception->exceptionType(); + if (exceptionType == Interrupted || exceptionType == Terminated) { while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) { // Don't need handler checks or anything, we just want to unroll all the JS callframes possible. } @@ -579,8 +580,8 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { *exception = createStackOverflowError(callFrame); return jsNull(); } @@ -640,8 +641,8 @@ JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { *exception = createStackOverflowError(callFrame); return jsNull(); } @@ -702,8 +703,8 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { *exception = createStackOverflowError(callFrame); return CallFrameClosure(); } @@ -778,8 +779,8 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { *exception = createStackOverflowError(callFrame); return jsNull(); } @@ -1030,8 +1031,20 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* // Cache hit: Specialize instruction and ref Structures. if (slot.slotBase() == baseValue) { - vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_self) : getOpcode(op_get_by_id_self); - vPC[5] = slot.cachedOffset(); + switch (slot.cachedPropertyType()) { + case PropertySlot::Getter: + vPC[0] = getOpcode(op_get_by_id_getter_self); + vPC[5] = slot.cachedOffset(); + break; + case PropertySlot::Custom: + vPC[0] = getOpcode(op_get_by_id_custom_self); + vPC[5] = slot.customGetter(); + break; + default: + vPC[0] = getOpcode(op_get_by_id_self); + vPC[5] = slot.cachedOffset(); + break; + } codeBlock->refStructures(vPC); return; @@ -1056,10 +1069,22 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* } ASSERT(!baseObject->structure()->isUncacheableDictionary()); - - vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_proto) : getOpcode(op_get_by_id_proto); + + switch (slot.cachedPropertyType()) { + case PropertySlot::Getter: + vPC[0] = getOpcode(op_get_by_id_getter_proto); + vPC[6] = offset; + break; + case PropertySlot::Custom: + vPC[0] = getOpcode(op_get_by_id_custom_proto); + vPC[6] = slot.customGetter(); + break; + default: + vPC[0] = getOpcode(op_get_by_id_proto); + vPC[6] = offset; + break; + } vPC[5] = baseObject->structure(); - vPC[6] = offset; codeBlock->refStructures(vPC); return; @@ -1072,11 +1097,24 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* return; } - vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_chain) : getOpcode(op_get_by_id_chain); + + switch (slot.cachedPropertyType()) { + case PropertySlot::Getter: + vPC[0] = getOpcode(op_get_by_id_getter_chain); + vPC[7] = offset; + break; + case PropertySlot::Custom: + vPC[0] = getOpcode(op_get_by_id_custom_chain); + vPC[7] = slot.customGetter(); + break; + default: + vPC[0] = getOpcode(op_get_by_id_chain); + vPC[7] = offset; + break; + } vPC[4] = structure; vPC[5] = structure->prototypeChain(callFrame); vPC[6] = count; - vPC[7] = offset; codeBlock->refStructures(vPC); } @@ -1137,7 +1175,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #define CHECK_FOR_TIMEOUT() \ if (!--tickCount) { \ - if (globalData->timeoutChecker.didTimeOut(callFrame)) { \ + if (globalData->terminator.shouldTerminate() || globalData->timeoutChecker.didTimeOut(callFrame)) { \ exceptionValue = jsNull(); \ goto vm_throw; \ } \ @@ -1199,20 +1237,6 @@ 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) @@ -1483,7 +1507,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int dst = vPC[1].u.operand; JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); - if (src.isInt32() && src.asInt32()) + if (src.isInt32() && (src.asInt32() & 0x7fffffff)) // non-zero and no overflow callFrame->r(dst) = jsNumber(callFrame, -src.asInt32()); else { JSValue result = jsNumber(callFrame, -src.toNumber(callFrame)); @@ -2207,6 +2231,48 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #if HAVE(COMPUTED_GOTO) skip_id_getter_proto: #endif +#if HAVE(COMPUTED_GOTO) + goto *(&&skip_id_custom_proto); +#endif + DEFINE_OPCODE(op_get_by_id_custom_proto) { + /* op_get_by_id_custom_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n) + + Cached property access: Attempts to use a cached named property getter + from the value base's prototype. If the cache misses, op_get_by_id_custom_proto + reverts to op_get_by_id. + */ + int base = vPC[2].u.operand; + JSValue baseValue = callFrame->r(base).jsValue(); + + if (LIKELY(baseValue.isCell())) { + JSCell* baseCell = asCell(baseValue); + Structure* structure = vPC[4].u.structure; + + if (LIKELY(baseCell->structure() == structure)) { + ASSERT(structure->prototypeForLookup(callFrame).isObject()); + JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); + Structure* prototypeStructure = vPC[5].u.structure; + + if (LIKELY(protoObject->structure() == prototypeStructure)) { + int dst = vPC[1].u.operand; + int property = vPC[3].u.operand; + Identifier& ident = callFrame->codeBlock()->identifier(property); + + PropertySlot::GetValueFunc getter = vPC[6].u.getterFunc; + JSValue result = getter(callFrame, protoObject, ident); + CHECK_FOR_EXCEPTION(); + callFrame->r(dst) = result; + vPC += OPCODE_LENGTH(op_get_by_id_custom_proto); + NEXT_INSTRUCTION(); + } + } + } + uncacheGetByID(callFrame->codeBlock(), vPC); + NEXT_INSTRUCTION(); + } +#if HAVE(COMPUTED_GOTO) + skip_id_custom_proto: +#endif DEFINE_OPCODE(op_get_by_id_self_list) { // Polymorphic self access caching currently only supported when JITting. ASSERT_NOT_REACHED(); @@ -2235,6 +2301,20 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi vPC += OPCODE_LENGTH(op_get_by_id_proto_list); NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_get_by_id_custom_self_list) { + // Polymorphic self access caching currently only supported when JITting. + ASSERT_NOT_REACHED(); + // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)! + vPC += OPCODE_LENGTH(op_get_by_id_custom_self_list); + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_get_by_id_custom_proto_list) { + // Polymorphic prototype access caching currently only supported when JITting. + ASSERT_NOT_REACHED(); + // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)! + vPC += OPCODE_LENGTH(op_get_by_id_proto_list); + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_get_by_id_chain) { /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) @@ -2324,6 +2404,43 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #if HAVE(COMPUTED_GOTO) skip_id_getter_self: #endif +#if HAVE(COMPUTED_GOTO) + goto *(&&skip_id_custom_self); +#endif + DEFINE_OPCODE(op_get_by_id_custom_self) { + /* op_get_by_id_custom_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n) + + Cached property access: Attempts to use a cached named property getter + from the value base. If the cache misses, op_get_by_id_custom_self reverts to + op_get_by_id. + */ + int base = vPC[2].u.operand; + JSValue baseValue = callFrame->r(base).jsValue(); + + if (LIKELY(baseValue.isCell())) { + JSCell* baseCell = asCell(baseValue); + Structure* structure = vPC[4].u.structure; + + if (LIKELY(baseCell->structure() == structure)) { + ASSERT(baseCell->isObject()); + int dst = vPC[1].u.operand; + int property = vPC[3].u.operand; + Identifier& ident = callFrame->codeBlock()->identifier(property); + + PropertySlot::GetValueFunc getter = vPC[5].u.getterFunc; + JSValue result = getter(callFrame, baseValue, ident); + CHECK_FOR_EXCEPTION(); + callFrame->r(dst) = result; + vPC += OPCODE_LENGTH(op_get_by_id_custom_self); + NEXT_INSTRUCTION(); + } + } + uncacheGetByID(callFrame->codeBlock(), vPC); + NEXT_INSTRUCTION(); + } +#if HAVE(COMPUTED_GOTO) +skip_id_custom_self: +#endif DEFINE_OPCODE(op_get_by_id_generic) { /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) @@ -2379,7 +2496,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSObject* getter = getterSetter->getter(); CallData callData; CallType callType = getter->getCallData(callData); - JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList()); + JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList()); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; } else @@ -2399,6 +2516,58 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #if HAVE(COMPUTED_GOTO) skip_id_getter_chain: #endif +#if HAVE(COMPUTED_GOTO) + goto *(&&skip_id_custom_chain); +#endif + DEFINE_OPCODE(op_get_by_id_custom_chain) { + /* op_get_by_id_custom_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) + + Cached property access: Attempts to use a cached named property getter on the + value base's prototype chain. If the cache misses, op_get_by_id_custom_chain + reverts to op_get_by_id. + */ + int base = vPC[2].u.operand; + JSValue baseValue = callFrame->r(base).jsValue(); + + if (LIKELY(baseValue.isCell())) { + JSCell* baseCell = asCell(baseValue); + Structure* structure = vPC[4].u.structure; + + if (LIKELY(baseCell->structure() == structure)) { + RefPtr<Structure>* it = vPC[5].u.structureChain->head(); + size_t count = vPC[6].u.operand; + RefPtr<Structure>* end = it + count; + + while (true) { + JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); + + if (UNLIKELY(baseObject->structure() != (*it).get())) + break; + + if (++it == end) { + int dst = vPC[1].u.operand; + int property = vPC[3].u.operand; + Identifier& ident = callFrame->codeBlock()->identifier(property); + + PropertySlot::GetValueFunc getter = vPC[7].u.getterFunc; + JSValue result = getter(callFrame, baseObject, ident); + CHECK_FOR_EXCEPTION(); + callFrame->r(dst) = result; + vPC += OPCODE_LENGTH(op_get_by_id_custom_chain); + NEXT_INSTRUCTION(); + } + + // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype. + baseCell = baseObject; + } + } + } + uncacheGetByID(callFrame->codeBlock(), vPC); + NEXT_INSTRUCTION(); + } +#if HAVE(COMPUTED_GOTO) + skip_id_custom_chain: +#endif DEFINE_OPCODE(op_get_array_length) { /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) @@ -3085,7 +3254,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (value->length() != 1) vPC += defaultOffset; else - vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->data()[0], defaultOffset); + vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->characters()[0], defaultOffset); } NEXT_INSTRUCTION(); } diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h index e17b055..cf8b342 100644 --- a/JavaScriptCore/interpreter/Interpreter.h +++ b/JavaScriptCore/interpreter/Interpreter.h @@ -64,7 +64,7 @@ namespace JSC { WillExecuteStatement }; - enum { MaxMainThreadReentryDepth = 256, MaxSecondaryThreadReentryDepth = 32 }; + enum { MaxLargeThreadReentryDepth = 256, MaxSmallThreadReentryDepth = 32 }; class Interpreter : public FastAllocBase { friend class JIT; |
