summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/llint
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-10-22 15:40:17 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-10-22 15:40:17 +0200
commit43a42f108af6bcbd91f2672731c3047c26213af1 (patch)
tree7fa092e5f5d873c72f2486a70e26be26f7a38bec /Source/JavaScriptCore/llint
parentd9cf437c840c6eb7417bdd97e6c40979255d3158 (diff)
downloadqtwebkit-43a42f108af6bcbd91f2672731c3047c26213af1.tar.gz
Imported WebKit commit 302e7806bff028bd1167a1ec7c86a1ee00ecfb49 (http://svn.webkit.org/repository/webkit/trunk@132067)
New snapshot that fixes build without QtWidgets
Diffstat (limited to 'Source/JavaScriptCore/llint')
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.cpp118
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.h7
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter.asm450
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm127
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter64.asm140
5 files changed, 520 insertions, 322 deletions
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
index fbf5b8598..74beae98a 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -119,12 +119,20 @@ namespace JSC { namespace LLInt {
JSValue __rp_returnValue = (value); \
LLINT_CHECK_EXCEPTION(); \
LLINT_OP(1) = __rp_returnValue; \
- pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
- JSValue::encode(__rp_returnValue); \
+ LLINT_PROFILE_VALUE(opcode, __rp_returnValue); \
LLINT_END_IMPL(); \
} while (false)
+
+#define LLINT_PROFILE_VALUE(opcode, value) do { \
+ pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
+ JSValue::encode(value); \
+ } while (false)
+
#else // ENABLE(VALUE_PROFILER)
#define LLINT_RETURN_PROFILED(opcode, value) LLINT_RETURN(value)
+
+#define LLINT_PROFILE_VALUE(opcode, value) do { } while (false)
+
#endif // ENABLE(VALUE_PROFILER)
#define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
@@ -777,52 +785,84 @@ LLINT_SLOW_PATH_DECL(slow_path_in)
LLINT_SLOW_PATH_DECL(slow_path_resolve)
{
LLINT_BEGIN();
- LLINT_RETURN_PROFILED(op_resolve, JSScope::resolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
-}
+ Identifier ident = exec->codeBlock()->identifier(pc[2].u.operand);
+ ResolveOperations* operations = exec->codeBlock()->resolveOperations(pc[3].u.operand);
+ JSValue result = JSScope::resolve(exec, ident, operations);
+ ASSERT(operations->size());
+ ASSERT(operations == exec->codeBlock()->resolveOperations(pc[3].u.operand));
+ switch (operations->data()[0].m_operation) {
+ case ResolveOperation::GetAndReturnGlobalProperty:
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_resolve_global_property);
+ break;
-LLINT_SLOW_PATH_DECL(slow_path_resolve_skip)
-{
- LLINT_BEGIN();
- LLINT_RETURN_PROFILED(
- op_resolve_skip,
- JSScope::resolveSkip(
- exec,
- exec->codeBlock()->identifier(pc[2].u.operand),
- pc[3].u.operand));
-}
+ case ResolveOperation::GetAndReturnGlobalVar:
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_resolve_global_var);
+ break;
-LLINT_SLOW_PATH_DECL(slow_path_resolve_global)
-{
- LLINT_BEGIN();
- Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
- LLINT_RETURN_PROFILED(op_resolve_global, JSScope::resolveGlobal(exec, ident, exec->lexicalGlobalObject(), &pc[3].u.structure, &pc[4].u.operand));
-}
+ case ResolveOperation::SkipTopScopeNode:
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_resolve_scoped_var_with_top_scope_check);
+ break;
-LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic)
-{
- // FIXME: <rdar://problem/12185487> LLInt resolve_global_dynamic doesn't check intervening scopes for modification
- LLINT_BEGIN();
- Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
- LLINT_RETURN_PROFILED(op_resolve_global_dynamic, JSScope::resolveGlobal(exec, ident, exec->lexicalGlobalObject(), &pc[3].u.structure, &pc[4].u.operand));
+ case ResolveOperation::SkipScopes:
+ if (operations->data()[0].m_scopesToSkip)
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_resolve_scoped_var);
+ else
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_resolve_scoped_var_on_top_scope);
+ break;
+
+ default:
+ break;
+ }
+ LLINT_RETURN_PROFILED(op_resolve, result);
}
-LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic)
+LLINT_SLOW_PATH_DECL(slow_path_put_to_base)
{
LLINT_BEGIN();
- LLINT_RETURN_PROFILED(op_resolve_global_dynamic, JSScope::resolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
+ PutToBaseOperation* operation = exec->codeBlock()->putToBaseOperation(pc[4].u.operand);
+ JSScope::resolvePut(exec, LLINT_OP_C(1).jsValue(), exec->codeBlock()->identifier(pc[2].u.operand), LLINT_OP_C(3).jsValue(), operation);
+ switch (operation->m_kind) {
+ case PutToBaseOperation::VariablePut:
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_put_to_base_variable);
+ break;
+
+ default:
+ break;
+ }
+ LLINT_END();
}
LLINT_SLOW_PATH_DECL(slow_path_resolve_base)
{
LLINT_BEGIN();
Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
+ ResolveOperations* operations = exec->codeBlock()->resolveOperations(pc[4].u.operand);
+ JSValue result;
if (pc[3].u.operand) {
- if (JSValue result = JSScope::resolveBase(exec, ident, true))
- LLINT_RETURN(result);
- LLINT_THROW(globalData.exception);
+ result = JSScope::resolveBase(exec, ident, true, operations, exec->codeBlock()->putToBaseOperation(pc[5].u.operand));
+ if (!result)
+ LLINT_THROW(globalData.exception);
+ } else
+ result = JSScope::resolveBase(exec, ident, false, operations, exec->codeBlock()->putToBaseOperation(pc[5].u.operand));
+ ASSERT(operations->size());
+ switch (operations->data()[0].m_operation) {
+ case ResolveOperation::ReturnGlobalObjectAsBase:
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_resolve_base_to_global);
+ break;
+
+ case ResolveOperation::SkipTopScopeNode:
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_resolve_base_to_scope_with_top_scope_check);
+ break;
+
+ case ResolveOperation::SkipScopes:
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_resolve_base_to_scope);
+ break;
+
+ default:
+ break;
}
-
- LLINT_RETURN_PROFILED(op_resolve_base, JSScope::resolveBase(exec, ident, false));
+ LLINT_PROFILE_VALUE(op_resolve_base, result);
+ LLINT_RETURN(result);
}
LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists)
@@ -839,24 +879,26 @@ LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists)
LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base)
{
LLINT_BEGIN();
- JSValue result = JSScope::resolveWithBase(exec, exec->codeBlock()->identifier(pc[3].u.operand), &LLINT_OP(1));
+ ResolveOperations* operations = exec->codeBlock()->resolveOperations(pc[4].u.operand);
+ JSValue result = JSScope::resolveWithBase(exec, exec->codeBlock()->identifier(pc[3].u.operand), &LLINT_OP(1), operations, exec->codeBlock()->putToBaseOperation(pc[5].u.operand));
LLINT_CHECK_EXCEPTION();
LLINT_OP(2) = result;
- // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
+ LLINT_PROFILE_VALUE(op_resolve_with_base, result);
LLINT_END();
}
LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this)
{
LLINT_BEGIN();
- JSValue result = JSScope::resolveWithThis(exec, exec->codeBlock()->identifier(pc[3].u.operand), &LLINT_OP(1));
+ ResolveOperations* operations = exec->codeBlock()->resolveOperations(pc[4].u.operand);
+ JSValue result = JSScope::resolveWithThis(exec, exec->codeBlock()->identifier(pc[3].u.operand), &LLINT_OP(1), operations);
LLINT_CHECK_EXCEPTION();
LLINT_OP(2) = result;
- // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
+ LLINT_PROFILE_VALUE(op_resolve_with_this, result);
LLINT_END();
}
-LLINT_SLOW_PATH_DECL(slow_path_put_global_var_check)
+LLINT_SLOW_PATH_DECL(slow_path_init_global_const_check)
{
LLINT_BEGIN();
CodeBlock* codeBlock = exec->codeBlock();
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.h b/Source/JavaScriptCore/llint/LLIntSlowPaths.h
index 3d770f3c5..f78476841 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.h
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.h
@@ -157,15 +157,12 @@ LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_is_object);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_is_function);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_in);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve);
-LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_skip);
-LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_global);
-LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_global_dynamic);
-LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_for_resolve_global_dynamic);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_to_base);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_base);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_ensure_property_exists);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_with_base);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_with_this);
-LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_global_var_check);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_init_global_const_check);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id);
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
index ad509e05d..022637dbe 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
@@ -54,8 +54,28 @@ if JSVALUE64
const PB = t6
const tagTypeNumber = csr1
const tagMask = csr2
+
+ macro loadisFromInstruction(offset, dest)
+ loadis offset * 8[PB, PC, 8], dest
+ end
+
+ macro loadpFromInstruction(offset, dest)
+ loadp offset * 8[PB, PC, 8], dest
+ end
+
+ macro storepToInstruction(value, offset)
+ storep value, offset * 8[PB, PC, 8]
+ end
+
else
const PC = t4
+ macro loadisFromInstruction(offset, dest)
+ loadis offset * 4[PC], dest
+ end
+
+ macro loadpFromInstruction(offset, dest)
+ loadp offset * 4[PC], dest
+ end
end
# Constants for reasoning about value representation.
@@ -100,6 +120,29 @@ const HashFlags8BitBuffer = 64
# Copied from PropertyOffset.h
const firstOutOfLineOffset = 100
+# From ResolveOperations.h
+const ResolveOperationFail = 0
+const ResolveOperationSetBaseToUndefined = 1
+const ResolveOperationReturnScopeAsBase = 2
+const ResolveOperationSetBaseToScope = 3
+const ResolveOperationSetBaseToGlobal = 4
+const ResolveOperationGetAndReturnScopedVar = 5
+const ResolveOperationGetAndReturnGlobalVar = 6
+const ResolveOperationGetAndReturnGlobalVarWatchable = 7
+const ResolveOperationSkipTopScopeNode = 8
+const ResolveOperationSkipScopes = 9
+const ResolveOperationReturnGlobalObjectAsBase = 10
+const ResolveOperationGetAndReturnGlobalProperty = 11
+const ResolveOperationCheckForDynamicEntriesBeforeGlobalScope = 12
+
+const PutToBaseOperationKindUninitialised = 0
+const PutToBaseOperationKindGeneric = 1
+const PutToBaseOperationKindReadonly = 2
+const PutToBaseOperationKindGlobalVariablePut = 3
+const PutToBaseOperationKindGlobalVariablePutChecked = 4
+const PutToBaseOperationKindGlobalPropertyPut = 5
+const PutToBaseOperationKindVariablePut = 6
+
# Allocation constants
if JSVALUE64
const JSFinalObjectSizeClassIndex = 1
@@ -196,13 +239,8 @@ macro arrayProfile(structureAndIndexingType, profile, scratch)
const indexingType = structureAndIndexingType
if VALUE_PROFILER
storep structure, ArrayProfile::m_lastSeenStructure[profile]
- loadb Structure::m_indexingType[structure], indexingType
- move 1, scratch
- lshifti indexingType, scratch
- ori scratch, ArrayProfile::m_observedArrayModes[profile]
- else
- loadb Structure::m_indexingType[structure], indexingType
end
+ loadb Structure::m_indexingType[structure], indexingType
end
macro checkSwitchToJIT(increment, action)
@@ -499,41 +537,417 @@ _llint_op_in:
callSlowPath(_llint_slow_path_in)
dispatch(4)
+macro getPutToBaseOperationField(scratch, scratch1, fieldOffset, fieldGetter)
+ loadisFromInstruction(4, scratch)
+ mulp sizeof PutToBaseOperation, scratch, scratch
+ loadp CodeBlock[cfr], scratch1
+ loadp VectorBufferOffset + CodeBlock::m_putToBaseOperations[scratch1], scratch1
+ fieldGetter(fieldOffset[scratch1, scratch, 1])
+end
+
+macro moveJSValueFromRegisterWithoutProfiling(value, destBuffer, destOffsetReg)
+ storep value, [destBuffer, destOffsetReg, 8]
+end
+
+
+macro moveJSValueFromRegistersWithoutProfiling(tag, payload, destBuffer, destOffsetReg)
+ storep tag, TagOffset[destBuffer, destOffsetReg, 8]
+ storep payload, PayloadOffset[destBuffer, destOffsetReg, 8]
+end
+
+macro putToBaseVariableBody(variableOffset, scratch1, scratch2, scratch3)
+ loadisFromInstruction(1, scratch1)
+ loadp PayloadOffset[cfr, scratch1, 8], scratch1
+ loadp JSVariableObject::m_registers[scratch1], scratch1
+ loadisFromInstruction(3, scratch2)
+ if JSVALUE64
+ loadConstantOrVariable(scratch2, scratch3)
+ moveJSValueFromRegisterWithoutProfiling(scratch3, scratch1, variableOffset)
+ else
+ loadConstantOrVariable2Reg(scratch2, scratch3, scratch2) # scratch3=tag, scratch2=payload
+ moveJSValueFromRegistersWithoutProfiling(scratch3, scratch2, scratch1, variableOffset)
+ end
+end
+
+_llint_op_put_to_base_variable:
+ traceExecution()
+ getPutToBaseOperationField(t0, t1, PutToBaseOperation::m_offset, macro(addr)
+ loadis addr, t0
+ end)
+ putToBaseVariableBody(t0, t1, t2, t3)
+ dispatch(5)
+
+_llint_op_put_to_base:
+ traceExecution()
+ getPutToBaseOperationField(t0, t1, 0, macro(addr)
+ leap addr, t0
+ bbneq PutToBaseOperation::m_kindAsUint8[t0], PutToBaseOperationKindVariablePut, .notPutToBaseVariable
+ loadis PutToBaseOperation::m_offset[t0], t0
+ putToBaseVariableBody(t0, t1, t2, t3)
+ dispatch(5)
+ .notPutToBaseVariable:
+ end)
+ callSlowPath(_llint_slow_path_put_to_base)
+ dispatch(5)
+
+macro getResolveOperation(resolveOperationIndex, dest, scratch)
+ loadisFromInstruction(resolveOperationIndex, dest)
+ mulp sizeof ResolveOperations, dest, dest
+ loadp CodeBlock[cfr], scratch
+ loadp VectorBufferOffset + CodeBlock::m_resolveOperations[scratch], scratch
+ loadp VectorBufferOffset[scratch, dest, 1], dest
+end
+
+macro getScope(loadInitialScope, scopeCount, dest, scratch)
+ loadInitialScope(dest)
+ loadi scopeCount, scratch
+
+ btiz scratch, .done
+.loop:
+ loadp JSScope::m_next[dest], dest
+ subi 1, scratch
+ btinz scratch, .loop
+
+.done:
+end
+
+macro moveJSValue(sourceBuffer, sourceOffsetReg, destBuffer, destOffsetReg, profileOffset, scratchRegister)
+ if JSVALUE64
+ loadp [sourceBuffer, sourceOffsetReg, 8], scratchRegister
+ storep scratchRegister, [destBuffer, destOffsetReg, 8]
+ loadpFromInstruction(profileOffset, destOffsetReg)
+ valueProfile(scratchRegister, destOffsetReg)
+ else
+ loadp PayloadOffset[sourceBuffer, sourceOffsetReg, 8], scratchRegister
+ storep scratchRegister, PayloadOffset[destBuffer, destOffsetReg, 8]
+ loadp TagOffset[sourceBuffer, sourceOffsetReg, 8], sourceOffsetReg
+ storep sourceOffsetReg, TagOffset[destBuffer, destOffsetReg, 8]
+ loadpFromInstruction(profileOffset, destOffsetReg)
+ valueProfile(sourceOffsetReg, scratchRegister, destOffsetReg)
+ end
+end
+
+macro moveJSValueFromSlot(slot, destBuffer, destOffsetReg, profileOffset, scratchRegister)
+ if JSVALUE64
+ loadp [slot], scratchRegister
+ storep scratchRegister, [destBuffer, destOffsetReg, 8]
+ loadpFromInstruction(profileOffset, destOffsetReg)
+ valueProfile(scratchRegister, destOffsetReg)
+ else
+ loadp PayloadOffset[slot], scratchRegister
+ storep scratchRegister, PayloadOffset[destBuffer, destOffsetReg, 8]
+ loadp TagOffset[slot], slot
+ storep slot, TagOffset[destBuffer, destOffsetReg, 8]
+ loadpFromInstruction(profileOffset, destOffsetReg)
+ valueProfile(slot, scratchRegister, destOffsetReg)
+ end
+end
+
+macro moveJSValueFromRegister(value, destBuffer, destOffsetReg, profileOffset)
+ storep value, [destBuffer, destOffsetReg, 8]
+ loadpFromInstruction(profileOffset, destOffsetReg)
+ valueProfile(value, destOffsetReg)
+end
+
+macro moveJSValueFromRegisters(tag, payload, destBuffer, destOffsetReg, profileOffset)
+ storep tag, TagOffset[destBuffer, destOffsetReg, 8]
+ storep payload, PayloadOffset[destBuffer, destOffsetReg, 8]
+ loadpFromInstruction(profileOffset, destOffsetReg)
+ valueProfile(tag, payload, destOffsetReg)
+end
+
+_llint_op_resolve_global_property:
+ traceExecution()
+ getResolveOperation(3, t0, t1)
+ loadp CodeBlock[cfr], t1
+ loadp CodeBlock::m_globalObject[t1], t1
+ loadp ResolveOperation::m_structure[t0], t2
+ bpneq JSCell::m_structure[t1], t2, _llint_op_resolve
+ loadis ResolveOperation::m_offset[t0], t0
+ if JSVALUE64
+ loadPropertyAtVariableOffsetKnownNotInline(t0, t1, t2)
+ loadisFromInstruction(1, t0)
+ moveJSValueFromRegister(t2, cfr, t0, 4)
+ else
+ loadPropertyAtVariableOffsetKnownNotInline(t0, t1, t2, t3)
+ loadisFromInstruction(1, t0)
+ moveJSValueFromRegisters(t2, t3, cfr, t0, 4)
+ end
+ dispatch(5)
+
+_llint_op_resolve_global_var:
+ traceExecution()
+ getResolveOperation(3, t0, t1)
+ loadp ResolveOperation::m_registerAddress[t0], t0
+ loadisFromInstruction(1, t1)
+ moveJSValueFromSlot(t0, cfr, t1, 4, t3)
+ dispatch(5)
+
+macro resolveScopedVarBody(resolveOperations)
+ # First ResolveOperation is to skip scope chain nodes
+ getScope(macro(dest)
+ loadp ScopeChain + PayloadOffset[cfr], dest
+ end,
+ ResolveOperation::m_scopesToSkip[resolveOperations], t1, t2)
+ loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
+
+ # Second ResolveOperation tells us what offset to use
+ loadis ResolveOperation::m_offset + sizeof ResolveOperation[resolveOperations], t2
+ loadisFromInstruction(1, t3)
+ moveJSValue(t1, t2, cfr, t3, 4, t0)
+end
+
+_llint_op_resolve_scoped_var:
+ traceExecution()
+ getResolveOperation(3, t0, t1)
+ resolveScopedVarBody(t0)
+ dispatch(5)
+
+_llint_op_resolve_scoped_var_on_top_scope:
+ traceExecution()
+ getResolveOperation(3, t0, t1)
+
+ # Load destination index
+ loadisFromInstruction(1, t3)
+
+ # We know we want the top scope chain entry
+ loadp ScopeChain + PayloadOffset[cfr], t1
+ loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
+
+ # Second ResolveOperation tells us what offset to use
+ loadis ResolveOperation::m_offset + sizeof ResolveOperation[t0], t2
+
+ moveJSValue(t1, t2, cfr, t3, 4, t0)
+ dispatch(5)
+
+_llint_op_resolve_scoped_var_with_top_scope_check:
+ traceExecution()
+ getResolveOperation(3, t0, t1)
+ # First ResolveOperation tells us what register to check
+ loadis ResolveOperation::m_activationRegister[t0], t1
+
+ loadp PayloadOffset[cfr, t1, 8], t1
+
+ getScope(macro(dest)
+ btpz t1, .scopeChainNotCreated
+ loadp JSScope::m_next[t1], dest
+ jmp .done
+ .scopeChainNotCreated:
+ loadp ScopeChain + PayloadOffset[cfr], dest
+ .done:
+ end,
+ # Second ResolveOperation tells us how many more nodes to skip
+ ResolveOperation::m_scopesToSkip + sizeof ResolveOperation[t0], t1, t2)
+ loadp JSVariableObject::m_registers[t1], t1 # t1 now contains the activation registers
+
+ # Third operation tells us what offset to use
+ loadis ResolveOperation::m_offset + 2 * sizeof ResolveOperation[t0], t2
+ loadisFromInstruction(1, t3)
+ moveJSValue(t1, t2, cfr, t3, 4, t0)
+ dispatch(5)
_llint_op_resolve:
traceExecution()
+ getResolveOperation(3, t0, t1)
+ btpz t0, .noInstructions
+ loadis ResolveOperation::m_operation[t0], t1
+ bineq t1, ResolveOperationSkipScopes, .notSkipScopes
+ resolveScopedVarBody(t0)
+ dispatch(5)
+.notSkipScopes:
+ bineq t1, ResolveOperationGetAndReturnGlobalVar, .notGetAndReturnGlobalVar
+ loadp ResolveOperation::m_registerAddress[t0], t0
+ loadisFromInstruction(1, t1)
+ moveJSValueFromSlot(t0, cfr, t1, 4, t3)
+ dispatch(5)
+.notGetAndReturnGlobalVar:
+
+.noInstructions:
callSlowPath(_llint_slow_path_resolve)
- dispatch(4)
+ dispatch(5)
+
+_llint_op_resolve_base_to_global:
+ traceExecution()
+ loadp CodeBlock[cfr], t1
+ loadp CodeBlock::m_globalObject[t1], t1
+ loadisFromInstruction(1, t3)
+ if JSVALUE64
+ moveJSValueFromRegister(t1, cfr, t3, 6)
+ else
+ move CellTag, t2
+ moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
+ end
+ dispatch(7)
+_llint_op_resolve_base_to_global_dynamic:
+ jmp _llint_op_resolve_base
-_llint_op_resolve_skip:
+_llint_op_resolve_base_to_scope:
traceExecution()
- callSlowPath(_llint_slow_path_resolve_skip)
- dispatch(5)
+ getResolveOperation(4, t0, t1)
+ # First ResolveOperation is to skip scope chain nodes
+ getScope(macro(dest)
+ loadp ScopeChain + PayloadOffset[cfr], dest
+ end,
+ ResolveOperation::m_scopesToSkip[t0], t1, t2)
+ loadisFromInstruction(1, t3)
+ if JSVALUE64
+ moveJSValueFromRegister(t1, cfr, t3, 6)
+ else
+ move CellTag, t2
+ moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
+ end
+ dispatch(7)
+_llint_op_resolve_base_to_scope_with_top_scope_check:
+ traceExecution()
+ getResolveOperation(4, t0, t1)
+ # First ResolveOperation tells us what register to check
+ loadis ResolveOperation::m_activationRegister[t0], t1
+
+ loadp PayloadOffset[cfr, t1, 8], t1
+
+ getScope(macro(dest)
+ btpz t1, .scopeChainNotCreated
+ loadp JSScope::m_next[t1], dest
+ jmp .done
+ .scopeChainNotCreated:
+ loadp ScopeChain + PayloadOffset[cfr], dest
+ .done:
+ end,
+ # Second ResolveOperation tells us how many more nodes to skip
+ ResolveOperation::m_scopesToSkip + sizeof ResolveOperation[t0], t1, t2)
+
+ loadisFromInstruction(1, t3)
+ if JSVALUE64
+ moveJSValueFromRegister(t1, cfr, t3, 6)
+ else
+ move CellTag, t2
+ moveJSValueFromRegisters(t2, t1, cfr, t3, 6)
+ end
+ dispatch(7)
_llint_op_resolve_base:
traceExecution()
callSlowPath(_llint_slow_path_resolve_base)
- dispatch(5)
-
+ dispatch(7)
_llint_op_ensure_property_exists:
traceExecution()
callSlowPath(_llint_slow_path_ensure_property_exists)
dispatch(3)
+macro interpretResolveWithBase(opcodeLength, slowPath)
+ traceExecution()
+ getResolveOperation(4, t0, t1)
+ btpz t0, .slowPath
+
+ loadp ScopeChain[cfr], t3
+ # Get the base
+ loadis ResolveOperation::m_operation[t0], t2
+
+ bineq t2, ResolveOperationSkipScopes, .notSkipScopes
+ getScope(macro(dest) move t3, dest end,
+ ResolveOperation::m_scopesToSkip[t0], t1, t2)
+ move t1, t3
+ addp sizeof ResolveOperation, t0, t0
+ jmp .haveCorrectScope
+
+ .notSkipScopes:
+
+ bineq t2, ResolveOperationSkipTopScopeNode, .notSkipTopScopeNode
+ loadis ResolveOperation::m_activationRegister[t0], t1
+ loadp PayloadOffset[cfr, t1, 8], t1
+
+ getScope(macro(dest)
+ btpz t1, .scopeChainNotCreated
+ loadp JSScope::m_next[t1], dest
+ jmp .done
+ .scopeChainNotCreated:
+ loadp ScopeChain + PayloadOffset[cfr], dest
+ .done:
+ end,
+ sizeof ResolveOperation + ResolveOperation::m_scopesToSkip[t0], t1, t2)
+ move t1, t3
+ # We've handled two opcodes here
+ addp 2 * sizeof ResolveOperation, t0, t0
+
+ .notSkipTopScopeNode:
+
+ .haveCorrectScope:
+
+ # t3 now contains the correct Scope
+ # t0 contains a pointer to the current ResolveOperation
+
+ loadis ResolveOperation::m_operation[t0], t2
+ # t2 contains the next instruction
+
+ loadisFromInstruction(1, t1)
+ # t1 now contains the index for the base register
+
+ bineq t2, ResolveOperationSetBaseToScope, .notSetBaseToScope
+ storep t3, PayloadOffset[cfr, t1, 8]
+ if JSVALUE64
+ else
+ storep CellTag, TagOffset[cfr, t1, 8]
+ end
+ jmp .haveSetBase
+
+ .notSetBaseToScope:
+
+ bineq t2, ResolveOperationSetBaseToUndefined, .notSetBaseToUndefined
+ if JSVALUE64
+ storep ValueUndefined, PayloadOffset[cfr, t1, 8]
+ else
+ storep 0, PayloadOffset[cfr, t1, 8]
+ storep UndefinedTag, TagOffset[cfr, t1, 8]
+ end
+ jmp .haveSetBase
+
+ .notSetBaseToUndefined:
+ bineq t2, ResolveOperationSetBaseToGlobal, .slowPath
+ loadp JSCell::m_structure[t3], t2
+ loadp Structure::m_globalObject[t2], t2
+ storep t2, PayloadOffset[cfr, t1, 8]
+ if JSVALUE64
+ else
+ storep CellTag, TagOffset[cfr, t1, 8]
+ end
+
+ .haveSetBase:
+
+ # Get the value
+
+ # Load the operation into t2
+ loadis ResolveOperation::m_operation + sizeof ResolveOperation[t0], t2
+
+ # Load the index for the value register into t1
+ loadisFromInstruction(2, t1)
+
+ bineq t2, ResolveOperationGetAndReturnScopedVar, .notGetAndReturnScopedVar
+ loadp JSVariableObject::m_registers[t3], t3 # t3 now contains the activation registers
+
+ # Second ResolveOperation tells us what offset to use
+ loadis ResolveOperation::m_offset + sizeof ResolveOperation[t0], t2
+ moveJSValue(t3, t2, cfr, t1, opcodeLength - 1, t0)
+ dispatch(opcodeLength)
+
+ .notGetAndReturnScopedVar:
+ bineq t2, ResolveOperationGetAndReturnGlobalProperty, .slowPath
+ callSlowPath(slowPath)
+ dispatch(opcodeLength)
+
+.slowPath:
+ callSlowPath(slowPath)
+ dispatch(opcodeLength)
+end
_llint_op_resolve_with_base:
- traceExecution()
- callSlowPath(_llint_slow_path_resolve_with_base)
- dispatch(5)
+ interpretResolveWithBase(7, _llint_slow_path_resolve_with_base)
_llint_op_resolve_with_this:
- traceExecution()
- callSlowPath(_llint_slow_path_resolve_with_this)
- dispatch(5)
+ interpretResolveWithBase(6, _llint_slow_path_resolve_with_this)
macro withInlineStorage(object, propertyStorage, continuation)
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
index f0d45eb0e..d0072d714 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -976,126 +976,7 @@ macro resolveGlobal(size, slow)
valueProfile(t2, t3, t0)
end
-_llint_op_resolve_global:
- traceExecution()
- resolveGlobal(6, .opResolveGlobalSlow)
- dispatch(6)
-
-.opResolveGlobalSlow:
- callSlowPath(_llint_slow_path_resolve_global)
- dispatch(6)
-
-
-# Gives you the scope in t0, while allowing you to optionally perform additional checks on the
-# scopes as they are traversed. scopeCheck() is called with two arguments: the register
-# holding the scope, and a register that can be used for scratch. Note that this does not
-# use t3, so you can hold stuff in t3 if need be.
-macro getScope(deBruijinIndexOperand, scopeCheck)
- loadp ScopeChain + PayloadOffset[cfr], t0
- loadi deBruijinIndexOperand, t2
-
- btiz t2, .done
-
- loadp CodeBlock[cfr], t1
- bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
- btbz CodeBlock::m_needsFullScopeChain[t1], .loop
-
- loadi CodeBlock::m_activationRegister[t1], t1
-
- # Need to conditionally skip over one scope.
- bieq TagOffset[cfr, t1, 8], EmptyValueTag, .noActivation
- scopeCheck(t0, t1)
- loadp JSScope::m_next[t0], t0
-.noActivation:
- subi 1, t2
-
- btiz t2, .done
-.loop:
- scopeCheck(t0, t1)
- loadp JSScope::m_next[t0], t0
- subi 1, t2
- btinz t2, .loop
-
-.done:
-end
-
-_llint_op_resolve_global_dynamic:
- traceExecution()
- loadp CodeBlock[cfr], t3
- loadp CodeBlock::m_globalObject[t3], t3
- loadp JSGlobalObject::m_activationStructure[t3], t3
- getScope(
- 20[PC],
- macro (scope, scratch)
- bpneq JSCell::m_structure[scope], t3, .opResolveGlobalDynamicSuperSlow
- end)
- resolveGlobal(7, .opResolveGlobalDynamicSlow)
- dispatch(7)
-
-.opResolveGlobalDynamicSuperSlow:
- callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic)
- dispatch(7)
-
-.opResolveGlobalDynamicSlow:
- callSlowPath(_llint_slow_path_resolve_global_dynamic)
- dispatch(7)
-
-
-_llint_op_get_scoped_var:
- traceExecution()
- # Operands are as follows:
- # 4[PC] Destination for the load.
- # 8[PC] Index of register in the scope.
- # 12[PC] De Bruijin index.
- getScope(12[PC], macro (scope, scratch) end)
- loadi 4[PC], t1
- loadi 8[PC], t2
- loadp JSVariableObject::m_registers[t0], t0
- loadi TagOffset[t0, t2, 8], t3
- loadi PayloadOffset[t0, t2, 8], t0
- storei t3, TagOffset[cfr, t1, 8]
- storei t0, PayloadOffset[cfr, t1, 8]
- loadi 16[PC], t1
- valueProfile(t3, t0, t1)
- dispatch(5)
-
-
-_llint_op_put_scoped_var:
- traceExecution()
- getScope(8[PC], macro (scope, scratch) end)
- loadi 12[PC], t1
- loadConstantOrVariable(t1, t3, t2)
- loadi 4[PC], t1
- writeBarrier(t3, t2)
- loadp JSVariableObject::m_registers[t0], t0
- storei t3, TagOffset[t0, t1, 8]
- storei t2, PayloadOffset[t0, t1, 8]
- dispatch(4)
-
-
-macro getGlobalVar(size)
- traceExecution()
- loadp 8[PC], t0
- loadi 4[PC], t3
- loadi TagOffset[t0], t2
- loadi PayloadOffset[t0], t1
- storei t2, TagOffset[cfr, t3, 8]
- storei t1, PayloadOffset[cfr, t3, 8]
- loadi (size - 1) * 4[PC], t3
- valueProfile(t2, t1, t3)
- dispatch(size)
-end
-
-_llint_op_get_global_var:
- getGlobalVar(4)
-
-
-_llint_op_get_global_var_watchable:
- getGlobalVar(5)
-
-
_llint_op_init_global_const:
-_llint_op_put_global_var:
traceExecution()
loadi 8[PC], t1
loadi 4[PC], t0
@@ -1107,22 +988,20 @@ _llint_op_put_global_var:
_llint_op_init_global_const_check:
-_llint_op_put_global_var_check:
traceExecution()
loadp 12[PC], t2
loadi 8[PC], t1
loadi 4[PC], t0
- btbnz [t2], .opPutGlobalVarCheckSlow
+ btbnz [t2], .opInitGlobalConstCheckSlow
loadConstantOrVariable(t1, t2, t3)
writeBarrier(t2, t3)
storei t2, TagOffset[t0]
storei t3, PayloadOffset[t0]
dispatch(5)
-.opPutGlobalVarCheckSlow:
- callSlowPath(_llint_slow_path_put_global_var_check)
+.opInitGlobalConstCheckSlow:
+ callSlowPath(_llint_slow_path_init_global_const_check)
dispatch(5)
-
# We only do monomorphic get_by_id caching for now, and we do not modify the
# opcode. We do, however, allow for the cache to change anytime if fails, since
# ping-ponging is free. At best we get lucky and the get_by_id will continue
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
index 8b72674ab..59fa18ccf 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
@@ -815,139 +815,7 @@ macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
loadp (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value
end
-macro resolveGlobal(size, slow)
- # Operands are as follows:
- # 8[PB, PC, 8] Destination for the load.
- # 16[PB, PC, 8] Property identifier index in the code block.
- # 24[PB, PC, 8] Structure pointer, initialized to 0 by bytecode generator.
- # 32[PB, PC, 8] Offset in global object, initialized to 0 by bytecode generator.
- loadp CodeBlock[cfr], t0
- loadp CodeBlock::m_globalObject[t0], t0
- loadp JSCell::m_structure[t0], t1
- bpneq t1, 24[PB, PC, 8], slow
- loadis 32[PB, PC, 8], t1
- loadPropertyAtVariableOffsetKnownNotInline(t1, t0, t2)
- loadis 8[PB, PC, 8], t0
- storep t2, [cfr, t0, 8]
- loadp (size - 1) * 8[PB, PC, 8], t0
- valueProfile(t2, t0)
-end
-
-_llint_op_resolve_global:
- traceExecution()
- resolveGlobal(6, .opResolveGlobalSlow)
- dispatch(6)
-
-.opResolveGlobalSlow:
- callSlowPath(_llint_slow_path_resolve_global)
- dispatch(6)
-
-
-# Gives you the scope in t0, while allowing you to optionally perform additional checks on the
-# scopes as they are traversed. scopeCheck() is called with two arguments: the register
-# holding the scope, and a register that can be used for scratch. Note that this does not
-# use t3, so you can hold stuff in t3 if need be.
-macro getScope(deBruijinIndexOperand, scopeCheck)
- loadp ScopeChain[cfr], t0
- loadis deBruijinIndexOperand, t2
-
- btiz t2, .done
-
- loadp CodeBlock[cfr], t1
- bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
- btbz CodeBlock::m_needsFullScopeChain[t1], .loop
-
- loadis CodeBlock::m_activationRegister[t1], t1
-
- # Need to conditionally skip over one scope.
- btpz [cfr, t1, 8], .noActivation
- scopeCheck(t0, t1)
- loadp JSScope::m_next[t0], t0
-.noActivation:
- subi 1, t2
-
- btiz t2, .done
-.loop:
- scopeCheck(t0, t1)
- loadp JSScope::m_next[t0], t0
- subi 1, t2
- btinz t2, .loop
-
-.done:
-end
-
-_llint_op_resolve_global_dynamic:
- traceExecution()
- loadp CodeBlock[cfr], t3
- loadp CodeBlock::m_globalObject[t3], t3
- loadp JSGlobalObject::m_activationStructure[t3], t3
- getScope(
- 40[PB, PC, 8],
- macro (scope, scratch)
- bpneq JSCell::m_structure[scope], t3, .opResolveGlobalDynamicSuperSlow
- end)
- resolveGlobal(7, .opResolveGlobalDynamicSlow)
- dispatch(7)
-
-.opResolveGlobalDynamicSuperSlow:
- callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic)
- dispatch(7)
-
-.opResolveGlobalDynamicSlow:
- callSlowPath(_llint_slow_path_resolve_global_dynamic)
- dispatch(7)
-
-
-_llint_op_get_scoped_var:
- traceExecution()
- # Operands are as follows:
- # 8[PB, PC, 8] Destination for the load
- # 16[PB, PC, 8] Index of register in the scope
- # 24[PB, PC, 8] De Bruijin index.
- getScope(24[PB, PC, 8], macro (scope, scratch) end)
- loadis 8[PB, PC, 8], t1
- loadis 16[PB, PC, 8], t2
- loadp JSVariableObject::m_registers[t0], t0
- loadp [t0, t2, 8], t3
- storep t3, [cfr, t1, 8]
- loadp 32[PB, PC, 8], t1
- valueProfile(t3, t1)
- dispatch(5)
-
-
-_llint_op_put_scoped_var:
- traceExecution()
- getScope(16[PB, PC, 8], macro (scope, scratch) end)
- loadis 24[PB, PC, 8], t1
- loadConstantOrVariable(t1, t3)
- loadis 8[PB, PC, 8], t1
- writeBarrier(t3)
- loadp JSVariableObject::m_registers[t0], t0
- storep t3, [t0, t1, 8]
- dispatch(4)
-
-
-macro getGlobalVar(size)
- traceExecution()
- loadp 16[PB, PC, 8], t0
- loadis 8[PB, PC, 8], t3
- loadp [t0], t1
- storep t1, [cfr, t3, 8]
- loadp (size - 1) * 8[PB, PC, 8], t0
- valueProfile(t1, t0)
- dispatch(size)
-end
-
-_llint_op_get_global_var:
- getGlobalVar(4)
-
-
-_llint_op_get_global_var_watchable:
- getGlobalVar(5)
-
-
_llint_op_init_global_const:
-_llint_op_put_global_var:
traceExecution()
loadis 16[PB, PC, 8], t1
loadp 8[PB, PC, 8], t0
@@ -958,21 +826,19 @@ _llint_op_put_global_var:
_llint_op_init_global_const_check:
-_llint_op_put_global_var_check:
traceExecution()
loadp 24[PB, PC, 8], t2
loadis 16[PB, PC, 8], t1
loadp 8[PB, PC, 8], t0
- btbnz [t2], .opPutGlobalVarCheckSlow
+ btbnz [t2], .opInitGlobalConstCheckSlow
loadConstantOrVariable(t1, t2)
writeBarrier(t2)
storep t2, [t0]
dispatch(5)
-.opPutGlobalVarCheckSlow:
- callSlowPath(_llint_slow_path_put_global_var_check)
+.opInitGlobalConstCheckSlow:
+ callSlowPath(_llint_slow_path_init_global_const_check)
dispatch(5)
-
macro getById(getPropertyStorage)
traceExecution()
# We only do monomorphic get_by_id caching for now, and we do not modify the