summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/interpreter
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:31:00 +0100
committerSteve Block <steveblock@google.com>2010-05-11 14:42:12 +0100
commitdcc8cf2e65d1aa555cce12431a16547e66b469ee (patch)
tree92a8d65cd5383bca9749f5327fb5e440563926e6 /JavaScriptCore/interpreter
parentccac38a6b48843126402088a309597e682f40fe6 (diff)
downloadexternal_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.cpp239
-rw-r--r--JavaScriptCore/interpreter/Interpreter.h2
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;