diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-03 09:55:33 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-03 09:55:33 +0100 |
commit | cd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch) | |
tree | 8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Source/JavaScriptCore/bytecode | |
parent | d11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff) | |
download | qtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz |
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Source/JavaScriptCore/bytecode')
19 files changed, 1042 insertions, 119 deletions
diff --git a/Source/JavaScriptCore/bytecode/CallLinkInfo.h b/Source/JavaScriptCore/bytecode/CallLinkInfo.h index 8ec48e4e1..44d50a971 100644 --- a/Source/JavaScriptCore/bytecode/CallLinkInfo.h +++ b/Source/JavaScriptCore/bytecode/CallLinkInfo.h @@ -72,7 +72,7 @@ struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> { WriteBarrier<JSFunction> lastSeenCallee; bool hasSeenShouldRepatch : 1; bool isDFG : 1; - CallType callType : 2; + CallType callType : 6; unsigned bytecodeIndex; bool isLinked() { return callee; } diff --git a/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp b/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp new file mode 100644 index 000000000..f3fd5bb27 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CallLinkStatus.h" + +#include "CodeBlock.h" + +namespace JSC { + +CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex) +{ + UNUSED_PARAM(profiledBlock); + UNUSED_PARAM(bytecodeIndex); +#if ENABLE(JIT) && ENABLE(VALUE_PROFILER) + return CallLinkStatus( + profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get(), + profiledBlock->couldTakeSlowCase(bytecodeIndex)); +#else + return CallLinkStatus(0, false); +#endif +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/bytecode/CallLinkStatus.h b/Source/JavaScriptCore/bytecode/CallLinkStatus.h new file mode 100644 index 000000000..e1c741016 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/CallLinkStatus.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CallLinkStatus_h +#define CallLinkStatus_h + +namespace JSC { + +class JSFunction; +class CodeBlock; + +class CallLinkStatus { +public: + CallLinkStatus() + : m_callTarget(0) + , m_couldTakeSlowPath(false) + { + } + + CallLinkStatus(JSFunction* callTarget, bool couldTakeSlowPath) + : m_callTarget(callTarget) + , m_couldTakeSlowPath(couldTakeSlowPath) + { + } + + static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex); + + bool isSet() const { return !!m_callTarget; } + + bool operator!() const { return !m_callTarget; } + + bool couldTakeSlowPath() const { return m_couldTakeSlowPath; } + + JSFunction* callTarget() const { return m_callTarget; } + +private: + JSFunction* m_callTarget; + bool m_couldTakeSlowPath; +}; + +} // namespace JSC + +#endif // CallLinkStatus_h + diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 47745268c..4a953266e 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -78,7 +78,7 @@ static UString valueToSourceString(ExecState* exec, JSValue val) return "0"; if (val.isString()) - return makeUString("\"", escapeQuotes(val.toString(exec)), "\""); + return makeUString("\"", escapeQuotes(val.toString(exec)->value(exec)), "\""); return val.description(); } @@ -180,7 +180,16 @@ void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); - it += 4; + it += 5; +} + +void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const +{ + int func = (++it)->u.operand; + int argCount = (++it)->u.operand; + int registerOffset = (++it)->u.operand; + printf("[%4d] %s\t %s, %d, %d\n", location, op, registerName(exec, func).data(), argCount, registerOffset); + it += 2; } void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const @@ -522,7 +531,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_convert_this: { int r0 = (++it)->u.operand; - printf("[%4d] convert_this %s\n", location, registerName(exec, r0).data()); + printf("[%4d] convert_this\t %s\n", location, registerName(exec, r0).data()); break; } case op_new_object: { @@ -734,6 +743,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + it++; break; } case op_resolve_skip: { @@ -741,13 +751,14 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int id0 = (++it)->u.operand; int skipLevels = (++it)->u.operand; printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels); + it++; break; } case op_resolve_global: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; printf("[%4d] resolve_global\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); - it += 2; + it += 3; break; } case op_resolve_global_dynamic: { @@ -757,6 +768,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& ++it; int depth = (++it)->u.operand; printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth); + ++it; break; } case op_get_scoped_var: { @@ -764,6 +776,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int index = (++it)->u.operand; int skipLevels = (++it)->u.operand; printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), index, skipLevels); + it++; break; } case op_put_scoped_var: { @@ -777,6 +790,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int index = (++it)->u.operand; printf("[%4d] get_global_var\t %s, %d\n", location, registerName(exec, r0).data(), index); + it++; break; } case op_put_global_var: { @@ -790,6 +804,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int id0 = (++it)->u.operand; int isStrict = (++it)->u.operand; printf("[%4d] resolve_base%s\t %s, %s\n", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + it++; break; } case op_ensure_property_exists: { @@ -803,6 +818,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + it++; break; } case op_resolve_with_this: { @@ -810,6 +826,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; printf("[%4d] resolve_with_this %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + it++; break; } case op_get_by_id: { @@ -885,18 +902,12 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printPutByIdOp(exec, location, it, "put_by_id_generic"); break; } - case op_put_getter: { + case op_put_getter_setter: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); - break; - } - case op_put_setter: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); + int r2 = (++it)->u.operand; + printf("[%4d] put_getter_setter\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); break; } case op_method_check: { @@ -915,6 +926,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + it++; break; } case op_get_argument_by_val: { @@ -922,6 +934,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; printf("[%4d] get_argument_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + ++it; break; } case op_get_by_pname: { @@ -1119,17 +1132,11 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& break; } case op_call: { - int func = (++it)->u.operand; - int argCount = (++it)->u.operand; - int registerOffset = (++it)->u.operand; - printf("[%4d] call\t\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset); + printCallOp(exec, location, it, "call"); break; } case op_call_eval: { - int func = (++it)->u.operand; - int argCount = (++it)->u.operand; - int registerOffset = (++it)->u.operand; - printf("[%4d] call_eval\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset); + printCallOp(exec, location, it, "call_eval"); break; } case op_call_varargs: { @@ -1148,7 +1155,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_tear_off_arguments: { int r0 = (++it)->u.operand; - printf("[%4d] tear_off_arguments\t %s\n", location, registerName(exec, r0).data()); + printf("[%4d] tear_off_arguments %s\n", location, registerName(exec, r0).data()); break; } case op_ret: { @@ -1159,6 +1166,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_call_put_result: { int r0 = (++it)->u.operand; printf("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data()); + it++; break; } case op_ret_object_or_this: { @@ -1168,10 +1176,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& break; } case op_construct: { - int func = (++it)->u.operand; - int argCount = (++it)->u.operand; - int registerOffset = (++it)->u.operand; - printf("[%4d] construct\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset); + printCallOp(exec, location, it, "construct"); break; } case op_strcat: { @@ -1446,6 +1451,9 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab) , m_speculativeFailCounter(0) , m_optimizationDelayCounter(0) , m_reoptimizationRetryCounter(0) +#if ENABLE(JIT) + , m_canCompileWithDFGState(CompileWithDFGUnset) +#endif { setNumParameters(other.numParameters()); optimizeAfterWarmUp(); @@ -2054,6 +2062,16 @@ void CodeBlock::createActivation(CallFrame* callFrame) callFrame->uncheckedR(activationRegister()) = JSValue(activation); callFrame->setScopeChain(callFrame->scopeChain()->push(activation)); } + +unsigned CodeBlock::addOrFindConstant(JSValue v) +{ + unsigned numberOfConstants = numberOfConstantRegisters(); + for (unsigned i = 0; i < numberOfConstants; ++i) { + if (getConstant(FirstConstantRegisterIndex + i) == v) + return i; + } + return addConstant(v); +} #if ENABLE(JIT) void CodeBlock::unlinkCalls() @@ -2154,17 +2172,17 @@ JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* s return error; } -bool ProgramCodeBlock::canCompileWithDFG() +bool ProgramCodeBlock::canCompileWithDFGInternal() { return DFG::canCompileProgram(this); } -bool EvalCodeBlock::canCompileWithDFG() +bool EvalCodeBlock::canCompileWithDFGInternal() { return DFG::canCompileEval(this); } -bool FunctionCodeBlock::canCompileWithDFG() +bool FunctionCodeBlock::canCompileWithDFGInternal() { if (m_isConstructor) return DFG::canCompileFunctionForConstruct(this); diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index c440c72e1..23d6a6b6d 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -94,7 +94,7 @@ namespace JSC { Heap* m_heap; public: - virtual ~CodeBlock(); + JS_EXPORT_PRIVATE virtual ~CodeBlock(); int numParameters() const { return m_numParameters; } void setNumParameters(int newValue); @@ -388,7 +388,22 @@ namespace JSC { virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0; virtual void jettison() = 0; virtual CodeBlock* replacement() = 0; - virtual bool canCompileWithDFG() = 0; + + enum CompileWithDFGState { + CompileWithDFGFalse, + CompileWithDFGTrue, + CompileWithDFGUnset + }; + + virtual bool canCompileWithDFGInternal() = 0; + bool canCompileWithDFG() + { + bool result = canCompileWithDFGInternal(); + m_canCompileWithDFGState = result ? CompileWithDFGTrue : CompileWithDFGFalse; + return result; + } + CompileWithDFGState canCompileWithDFGState() { return m_canCompileWithDFGState; } + bool hasOptimizedReplacement() { ASSERT(getJITType() == JITCode::BaselineJIT); @@ -521,6 +536,11 @@ namespace JSC { { ValueProfile* result = WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset); ASSERT(result->m_bytecodeOffset != -1); + ASSERT(!hasInstructions() + || instructions()[bytecodeOffset + opcodeLength( + m_globalData->interpreter->getOpcodeID( + instructions()[ + bytecodeOffset].u.opcode)) - 1].u.profile == result); return result; } @@ -664,10 +684,22 @@ namespace JSC { return m_rareData && !!m_rareData->m_codeOrigins.size(); } - CodeOrigin codeOriginForReturn(ReturnAddressPtr returnAddress) + bool codeOriginForReturn(ReturnAddressPtr returnAddress, CodeOrigin& codeOrigin) { - ASSERT(hasCodeOrigins()); - return binarySearch<CodeOriginAtCallReturnOffset, unsigned, getCallReturnOffsetForCodeOrigin>(codeOrigins().begin(), codeOrigins().size(), getJITCode().offsetOf(returnAddress.value()))->codeOrigin; + if (!hasCodeOrigins()) + return false; + unsigned offset = getJITCode().offsetOf(returnAddress.value()); + CodeOriginAtCallReturnOffset* entry = binarySearch<CodeOriginAtCallReturnOffset, unsigned, getCallReturnOffsetForCodeOrigin>(codeOrigins().begin(), codeOrigins().size(), offset, WTF::KeyMustNotBePresentInArray); + if (entry->callReturnOffset != offset) + return false; + codeOrigin = entry->codeOrigin; + return true; + } + + CodeOrigin codeOrigin(unsigned index) + { + ASSERT(m_rareData); + return m_rareData->m_codeOrigins[index].codeOrigin; } bool addFrequentExitSite(const DFG::FrequentExitSite& site) @@ -686,11 +718,14 @@ namespace JSC { Identifier& identifier(int index) { return m_identifiers[index]; } size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); } - void addConstant(JSValue v) + unsigned addConstant(JSValue v) { + unsigned result = m_constantRegisters.size(); m_constantRegisters.append(WriteBarrier<Unknown>()); m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v); + return result; } + unsigned addOrFindConstant(JSValue); WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; } ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; } ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); } @@ -780,7 +815,7 @@ namespace JSC { // Functions for controlling when tiered compilation kicks in. This // controls both when the optimizing compiler is invoked and when OSR // entry happens. Two triggers exist: the loop trigger and the return - // trigger. In either case, when an addition to m_executeCounter + // trigger. In either case, when an addition to m_jitExecuteCounter // causes it to become non-negative, the optimizing compiler is // invoked. This includes a fast check to see if this CodeBlock has // already been optimized (i.e. replacement() returns a CodeBlock @@ -821,14 +856,14 @@ namespace JSC { return Options::executionCounterValueForOptimizeAfterLongWarmUp << reoptimizationRetryCounter(); } - int32_t* addressOfExecuteCounter() + int32_t* addressOfJITExecuteCounter() { - return &m_executeCounter; + return &m_jitExecuteCounter; } - static ptrdiff_t offsetOfExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_executeCounter); } + static ptrdiff_t offsetOfJITExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter); } - int32_t executeCounter() const { return m_executeCounter; } + int32_t jitExecuteCounter() const { return m_jitExecuteCounter; } unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; } @@ -837,7 +872,7 @@ namespace JSC { // expensive than executing baseline code. void optimizeNextInvocation() { - m_executeCounter = Options::executionCounterValueForOptimizeNextInvocation; + m_jitExecuteCounter = Options::executionCounterValueForOptimizeNextInvocation; } // Call this to prevent optimization from happening again. Note that @@ -847,7 +882,7 @@ namespace JSC { // the future as well. void dontOptimizeAnytimeSoon() { - m_executeCounter = Options::executionCounterValueForDontOptimizeAnytimeSoon; + m_jitExecuteCounter = Options::executionCounterValueForDontOptimizeAnytimeSoon; } // Call this to reinitialize the counter to its starting state, @@ -858,14 +893,14 @@ namespace JSC { // counter that this corresponds to is also available directly. void optimizeAfterWarmUp() { - m_executeCounter = counterValueForOptimizeAfterWarmUp(); + m_jitExecuteCounter = counterValueForOptimizeAfterWarmUp(); } // Call this to force an optimization trigger to fire only after // a lot of warm-up. void optimizeAfterLongWarmUp() { - m_executeCounter = counterValueForOptimizeAfterLongWarmUp(); + m_jitExecuteCounter = counterValueForOptimizeAfterLongWarmUp(); } // Call this to cause an optimization trigger to fire soon, but @@ -888,7 +923,7 @@ namespace JSC { // in the baseline code. void optimizeSoon() { - m_executeCounter = Options::executionCounterValueForOptimizeSoon << reoptimizationRetryCounter(); + m_jitExecuteCounter = Options::executionCounterValueForOptimizeSoon << reoptimizationRetryCounter(); } // The speculative JIT tracks its success rate, so that we can @@ -989,6 +1024,7 @@ namespace JSC { void printBinaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const; void printConditionalJump(ExecState*, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator&, int location, const char* op) const; void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const; + void printCallOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const; void printPutByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const; #endif void visitStructures(SlotVisitor&, Instruction* vPC) const; @@ -1129,7 +1165,7 @@ namespace JSC { OwnPtr<CodeBlock> m_alternative; - int32_t m_executeCounter; + int32_t m_jitExecuteCounter; uint32_t m_speculativeSuccessCounter; uint32_t m_speculativeFailCounter; uint8_t m_optimizationDelayCounter; @@ -1169,6 +1205,9 @@ namespace JSC { friend void WTF::deleteOwnedPtr<RareData>(RareData*); #endif OwnPtr<RareData> m_rareData; +#if ENABLE(JIT) + CompileWithDFGState m_canCompileWithDFGState; +#endif }; // Program code is not marked by any function, so we make the global object @@ -1208,7 +1247,7 @@ namespace JSC { virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); virtual void jettison(); virtual CodeBlock* replacement(); - virtual bool canCompileWithDFG(); + virtual bool canCompileWithDFGInternal(); #endif }; @@ -1242,7 +1281,7 @@ namespace JSC { virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); virtual void jettison(); virtual CodeBlock* replacement(); - virtual bool canCompileWithDFG(); + virtual bool canCompileWithDFGInternal(); #endif private: @@ -1279,7 +1318,7 @@ namespace JSC { virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); virtual void jettison(); virtual CodeBlock* replacement(); - virtual bool canCompileWithDFG(); + virtual bool canCompileWithDFGInternal(); #endif }; diff --git a/Source/JavaScriptCore/bytecode/CodeOrigin.h b/Source/JavaScriptCore/bytecode/CodeOrigin.h index 7b6ce7d48..25a116c55 100644 --- a/Source/JavaScriptCore/bytecode/CodeOrigin.h +++ b/Source/JavaScriptCore/bytecode/CodeOrigin.h @@ -38,29 +38,37 @@ class ExecutableBase; class JSFunction; struct CodeOrigin { - uint32_t bytecodeIndex; + // Bytecode offset that you'd use to re-execute this instruction. + unsigned bytecodeIndex : 29; + // Bytecode offset corresponding to the opcode that gives the result (needed to handle + // op_call/op_call_put_result and op_method_check/op_get_by_id). + unsigned valueProfileOffset : 3; + InlineCallFrame* inlineCallFrame; CodeOrigin() : bytecodeIndex(std::numeric_limits<uint32_t>::max()) + , valueProfileOffset(0) , inlineCallFrame(0) { } - explicit CodeOrigin(uint32_t bytecodeIndex) - : bytecodeIndex(bytecodeIndex) - , inlineCallFrame(0) - { - } - - explicit CodeOrigin(uint32_t bytecodeIndex, InlineCallFrame* inlineCallFrame) + explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0, unsigned valueProfileOffset = 0) : bytecodeIndex(bytecodeIndex) + , valueProfileOffset(valueProfileOffset) , inlineCallFrame(inlineCallFrame) { + ASSERT(bytecodeIndex < (1u << 29)); + ASSERT(valueProfileOffset < (1u << 3)); } bool isSet() const { return bytecodeIndex != std::numeric_limits<uint32_t>::max(); } + unsigned bytecodeIndexForValueProfile() const + { + return bytecodeIndex + valueProfileOffset; + } + // The inline depth is the depth of the inline stack, so 1 = not inlined, // 2 = inlined one deep, etc. unsigned inlineDepth() const; diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp new file mode 100644 index 000000000..5eff1d4a0 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GetByIdStatus.h" + +#include "CodeBlock.h" + +namespace JSC { + +GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident) +{ + UNUSED_PARAM(profiledBlock); + UNUSED_PARAM(bytecodeIndex); + UNUSED_PARAM(ident); +#if ENABLE(JIT) && ENABLE(VALUE_PROFILER) + // First check if it makes either calls, in which case we want to be super careful, or + // if it's not set at all, in which case we punt. + StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex); + if (!stubInfo.seen) + return GetByIdStatus(NoInformation, StructureSet(), notFound); + + PolymorphicAccessStructureList* list; + int listSize; + switch (stubInfo.accessType) { + case access_get_by_id_self_list: + list = stubInfo.u.getByIdSelfList.structureList; + listSize = stubInfo.u.getByIdSelfList.listSize; + break; + case access_get_by_id_proto_list: + list = stubInfo.u.getByIdProtoList.structureList; + listSize = stubInfo.u.getByIdProtoList.listSize; + break; + default: + list = 0; + listSize = 0; + break; + } + for (int i = 0; i < listSize; ++i) { + if (!list->list[i].isDirect) + return GetByIdStatus(MakesCalls, StructureSet(), notFound); + } + + // Next check if it takes slow case, in which case we want to be kind of careful. + if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex)) + return GetByIdStatus(TakesSlowPath, StructureSet(), notFound); + + // Finally figure out if we can derive an access strategy. + GetByIdStatus result; + switch (stubInfo.accessType) { + case access_unset: + return GetByIdStatus(NoInformation, StructureSet(), notFound); + + case access_get_by_id_self: { + Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get(); + result.m_offset = structure->get(*profiledBlock->globalData(), ident); + + if (result.m_offset != notFound) + result.m_structureSet.add(structure); + + if (result.m_offset != notFound) + ASSERT(result.m_structureSet.size()); + break; + } + + case access_get_by_id_self_list: { + PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList; + unsigned size = stubInfo.u.getByIdProtoList.listSize; + for (unsigned i = 0; i < size; ++i) { + ASSERT(list->list[i].isDirect); + + Structure* structure = list->list[i].base.get(); + if (result.m_structureSet.contains(structure)) + continue; + + size_t myOffset = structure->get(*profiledBlock->globalData(), ident); + + if (myOffset == notFound) { + result.m_offset = notFound; + break; + } + + if (!i) + result.m_offset = myOffset; + else if (result.m_offset != myOffset) { + result.m_offset = notFound; + break; + } + + result.m_structureSet.add(structure); + } + + if (result.m_offset != notFound) + ASSERT(result.m_structureSet.size()); + break; + } + + default: + ASSERT(result.m_offset == notFound); + break; + } + + if (result.m_offset == notFound) { + result.m_state = TakesSlowPath; + result.m_structureSet.clear(); + } else + result.m_state = SimpleDirect; + + return result; +#else // ENABLE(JIT) + return GetByIdStatus(NoInformation, StructureSet(), notFound); +#endif // ENABLE(JIT) +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.h b/Source/JavaScriptCore/bytecode/GetByIdStatus.h new file mode 100644 index 000000000..00e50e76d --- /dev/null +++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GetByIdStatus_h +#define GetByIdStatus_h + +#include "StructureSet.h" +#include <wtf/NotFound.h> + +namespace JSC { + +class CodeBlock; +class Identifier; + +class GetByIdStatus { +public: + enum State { + NoInformation, // It's uncached so we have no information. + SimpleDirect, // It's cached for a direct access to a known object property. + TakesSlowPath, // It's known to often take slow path. + MakesCalls // It's known to take paths that make calls. + }; + + GetByIdStatus() + : m_state(NoInformation) + , m_offset(notFound) + { + } + + GetByIdStatus(State state, const StructureSet& structureSet, size_t offset) + : m_state(state) + , m_structureSet(structureSet) + , m_offset(offset) + { + ASSERT((state == SimpleDirect) == (offset != notFound)); + } + + static GetByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&); + + State state() const { return m_state; } + + bool isSet() const { return m_state != NoInformation; } + bool operator!() const { return !isSet(); } + bool isSimpleDirect() const { return m_state == SimpleDirect; } + bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; } + bool makesCalls() const { return m_state == MakesCalls; } + + const StructureSet& structureSet() const { return m_structureSet; } + size_t offset() const { return m_offset; } + +private: + State m_state; + StructureSet m_structureSet; + size_t m_offset; +}; + +} // namespace JSC + +#endif // PropertyAccessStatus_h + diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h index 7e4413065..92118eeb2 100644 --- a/Source/JavaScriptCore/bytecode/Instruction.h +++ b/Source/JavaScriptCore/bytecode/Instruction.h @@ -48,6 +48,7 @@ namespace JSC { class JSCell; class Structure; class StructureChain; + struct ValueProfile; #if ENABLE(JIT) typedef MacroAssemblerCodeRef PolymorphicAccessStructureListStubRoutineType; @@ -99,6 +100,10 @@ namespace JSC { } } list[POLYMORPHIC_LIST_CACHE_SIZE]; + PolymorphicAccessStructureList() + { + } + PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, bool isDirect) { list[0].set(globalData, owner, stubRoutine, firstBase, isDirect); @@ -176,6 +181,8 @@ namespace JSC { } Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; } + + Instruction(ValueProfile* profile) { u.profile = profile; } union { Opcode opcode; @@ -184,6 +191,7 @@ namespace JSC { WriteBarrierBase<StructureChain> structureChain; WriteBarrierBase<JSCell> jsCell; PropertySlot::GetValueFunc getterFunc; + ValueProfile* profile; } u; private: diff --git a/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp b/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp new file mode 100644 index 000000000..e7d721c29 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MethodCallLinkStatus.h" + +#include "CodeBlock.h" + +namespace JSC { + +MethodCallLinkStatus MethodCallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex) +{ + UNUSED_PARAM(profiledBlock); + UNUSED_PARAM(bytecodeIndex); +#if ENABLE(JIT) && ENABLE(VALUE_PROFILER) + MethodCallLinkInfo& methodCall = profiledBlock->getMethodCallLinkInfo(bytecodeIndex); + + if (!methodCall.seen || !methodCall.cachedStructure) + return MethodCallLinkStatus(); + + if (methodCall.cachedPrototype.get() == profiledBlock->globalObject()->methodCallDummy()) { + return MethodCallLinkStatus( + methodCall.cachedStructure.get(), + 0, + methodCall.cachedFunction.get(), + 0); + } + + return MethodCallLinkStatus( + methodCall.cachedStructure.get(), + methodCall.cachedPrototypeStructure.get(), + methodCall.cachedFunction.get(), + methodCall.cachedPrototype.get()); +#else // ENABLE(JIT) + return MethodCallLinkStatus(); +#endif // ENABLE(JIT) +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h b/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h new file mode 100644 index 000000000..c3d11a1d8 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MethodCallLinkStatus_h +#define MethodCallLinkStatus_h + +namespace JSC { + +class CodeBlock; +class JSObject; +class Structure; + +class MethodCallLinkStatus { +public: + MethodCallLinkStatus() + : m_structure(0) + , m_prototypeStructure(0) + , m_function(0) + , m_prototype(0) + { + } + + MethodCallLinkStatus( + Structure* structure, + Structure* prototypeStructure, + JSObject* function, + JSObject* prototype) + : m_structure(structure) + , m_prototypeStructure(prototypeStructure) + , m_function(function) + , m_prototype(prototype) + { + if (!m_function) { + ASSERT(!m_structure); + ASSERT(!m_prototypeStructure); + ASSERT(!m_prototype); + } else + ASSERT(m_structure); + + ASSERT(!m_prototype == !m_prototypeStructure); + } + + static MethodCallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex); + + bool isSet() const { return !!m_function; } + bool operator!() const { return !m_function; } + + bool needsPrototypeCheck() const { return !!m_prototype; } + + Structure* structure() { return m_structure; } + Structure* prototypeStructure() { return m_prototypeStructure; } + JSObject* function() const { return m_function; } + JSObject* prototype() const { return m_prototype; } + +private: + Structure* m_structure; + Structure* m_prototypeStructure; + JSObject* m_function; + JSObject* m_prototype; +}; + +} // namespace JSC + +#endif // MethodCallLinkStatus_h + diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h index 4801e4c32..57633a338 100644 --- a/Source/JavaScriptCore/bytecode/Opcode.h +++ b/Source/JavaScriptCore/bytecode/Opcode.h @@ -95,45 +95,44 @@ namespace JSC { macro(op_is_function, 3) \ macro(op_in, 4) \ \ - macro(op_resolve, 3) \ - macro(op_resolve_skip, 4) \ - macro(op_resolve_global, 5) \ - macro(op_resolve_global_dynamic, 6) \ - macro(op_get_scoped_var, 4) \ + macro(op_resolve, 4) /* has value profiling */ \ + macro(op_resolve_skip, 5) /* has value profiling */ \ + macro(op_resolve_global, 6) /* has value profiling */ \ + macro(op_resolve_global_dynamic, 7) /* has value profiling */ \ + macro(op_get_scoped_var, 5) /* has value profiling */ \ macro(op_put_scoped_var, 4) \ - macro(op_get_global_var, 3) \ + macro(op_get_global_var, 4) /* has value profiling */ \ macro(op_put_global_var, 3) \ - macro(op_resolve_base, 4) \ + macro(op_resolve_base, 5) /* has value profiling */ \ macro(op_ensure_property_exists, 3) \ - macro(op_resolve_with_base, 4) \ - macro(op_resolve_with_this, 4) \ - macro(op_get_by_id, 8) \ - macro(op_get_by_id_self, 8) \ - macro(op_get_by_id_proto, 8) \ - macro(op_get_by_id_chain, 8) \ - macro(op_get_by_id_getter_self, 8) \ - macro(op_get_by_id_getter_proto, 8) \ - macro(op_get_by_id_getter_chain, 8) \ - macro(op_get_by_id_custom_self, 8) \ - macro(op_get_by_id_custom_proto, 8) \ - macro(op_get_by_id_custom_chain, 8) \ - macro(op_get_by_id_generic, 8) \ - macro(op_get_array_length, 8) \ - macro(op_get_string_length, 8) \ + macro(op_resolve_with_base, 5) /* has value profiling */ \ + macro(op_resolve_with_this, 5) /* has value profiling */ \ + macro(op_get_by_id, 9) /* has value profiling */ \ + macro(op_get_by_id_self, 9) /* has value profiling */ \ + macro(op_get_by_id_proto, 9) /* has value profiling */ \ + macro(op_get_by_id_chain, 9) /* has value profiling */ \ + macro(op_get_by_id_getter_self, 9) /* has value profiling */ \ + macro(op_get_by_id_getter_proto, 9) /* has value profiling */ \ + macro(op_get_by_id_getter_chain, 9) /* has value profiling */ \ + macro(op_get_by_id_custom_self, 9) /* has value profiling */ \ + macro(op_get_by_id_custom_proto, 9) /* has value profiling */ \ + macro(op_get_by_id_custom_chain, 9) /* has value profiling */ \ + macro(op_get_by_id_generic, 9) /* has value profiling */ \ + macro(op_get_array_length, 9) /* has value profiling */ \ + macro(op_get_string_length, 9) /* has value profiling */ \ macro(op_get_arguments_length, 4) \ macro(op_put_by_id, 9) \ macro(op_put_by_id_transition, 9) \ macro(op_put_by_id_replace, 9) \ macro(op_put_by_id_generic, 9) \ macro(op_del_by_id, 4) \ - macro(op_get_by_val, 4) \ - macro(op_get_argument_by_val, 4) \ + macro(op_get_by_val, 5) /* has value profiling */ \ + macro(op_get_argument_by_val, 5) /* must be the same size as op_get_by_val */ \ macro(op_get_by_pname, 7) \ macro(op_put_by_val, 4) \ macro(op_del_by_val, 4) \ macro(op_put_by_index, 4) \ - macro(op_put_getter, 4) \ - macro(op_put_setter, 4) \ + macro(op_put_getter_setter, 5) \ \ macro(op_jmp, 2) \ macro(op_jtrue, 3) \ @@ -170,7 +169,7 @@ namespace JSC { macro(op_tear_off_activation, 3) \ macro(op_tear_off_arguments, 2) \ macro(op_ret, 2) \ - macro(op_call_put_result, 2) \ + macro(op_call_put_result, 3) /* has value profiling */ \ macro(op_ret_object_or_this, 3) \ macro(op_method_check, 1) \ \ diff --git a/Source/JavaScriptCore/bytecode/PredictedType.cpp b/Source/JavaScriptCore/bytecode/PredictedType.cpp index 9356390a9..4b07ff446 100644 --- a/Source/JavaScriptCore/bytecode/PredictedType.cpp +++ b/Source/JavaScriptCore/bytecode/PredictedType.cpp @@ -92,6 +92,11 @@ const char* predictionToString(PredictedType value) ptr.strcat("Uint8array"); else isTop = false; + + if (value & PredictUint8ClampedArray) + ptr.strcat("Uint8clampedarray"); + else + isTop = false; if (value & PredictUint16Array) ptr.strcat("Uint16array"); @@ -184,6 +189,8 @@ PredictedType predictionFromClassInfo(const ClassInfo* classInfo) return PredictInt32Array; case TypedArrayUint8: return PredictUint8Array; + case TypedArrayUint8Clamped: + return PredictUint8ClampedArray; case TypedArrayUint16: return PredictUint16Array; case TypedArrayUint32: diff --git a/Source/JavaScriptCore/bytecode/PredictedType.h b/Source/JavaScriptCore/bytecode/PredictedType.h index 3ec03924a..47583361d 100644 --- a/Source/JavaScriptCore/bytecode/PredictedType.h +++ b/Source/JavaScriptCore/bytecode/PredictedType.h @@ -36,33 +36,34 @@ namespace JSC { class Structure; typedef uint32_t PredictedType; -static const PredictedType PredictNone = 0x00000000; // We don't know anything yet. -static const PredictedType PredictFinalObject = 0x00000001; // It's definitely a JSFinalObject. -static const PredictedType PredictArray = 0x00000002; // It's definitely a JSArray. -static const PredictedType PredictByteArray = 0x00000004; // It's definitely a JSByteArray or one of its subclasses. -static const PredictedType PredictFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses. -static const PredictedType PredictInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses. -static const PredictedType PredictInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses. -static const PredictedType PredictInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses. -static const PredictedType PredictUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses. -static const PredictedType PredictUint16Array = 0x00000100; // It's definitely an Uint16Array or one of its subclasses. -static const PredictedType PredictUint32Array = 0x00000200; // It's definitely an Uint32Array or one of its subclasses. -static const PredictedType PredictFloat32Array = 0x00000400; // It's definitely an Uint16Array or one of its subclasses. -static const PredictedType PredictFloat64Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses. -static const PredictedType PredictObjectOther = 0x00001000; // It's definitely an object but not JSFinalObject, JSArray, JSByteArray, or JSFunction. -static const PredictedType PredictObjectMask = 0x00001fff; // Bitmask used for testing for any kind of object prediction. -static const PredictedType PredictString = 0x00002000; // It's definitely a JSString. -static const PredictedType PredictCellOther = 0x00004000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString. -static const PredictedType PredictCell = 0x00007fff; // It's definitely a JSCell. -static const PredictedType PredictInt32 = 0x00008000; // It's definitely an Int32. -static const PredictedType PredictDoubleReal = 0x00010000; // It's definitely a non-NaN double. -static const PredictedType PredictDoubleNaN = 0x00020000; // It's definitely a NaN. -static const PredictedType PredictDouble = 0x00030000; // It's either a non-NaN or a NaN double. -static const PredictedType PredictNumber = 0x00038000; // It's either an Int32 or a Double. -static const PredictedType PredictBoolean = 0x00040000; // It's definitely a Boolean. -static const PredictedType PredictOther = 0x40000000; // It's definitely none of the above. -static const PredictedType PredictTop = 0x7fffffff; // It can be any of the above. -static const PredictedType FixedIndexedStorageMask = PredictByteArray | PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array; +static const PredictedType PredictNone = 0x00000000; // We don't know anything yet. +static const PredictedType PredictFinalObject = 0x00000001; // It's definitely a JSFinalObject. +static const PredictedType PredictArray = 0x00000002; // It's definitely a JSArray. +static const PredictedType PredictByteArray = 0x00000004; // It's definitely a JSByteArray or one of its subclasses. +static const PredictedType PredictFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses. +static const PredictedType PredictInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses. +static const PredictedType PredictInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses. +static const PredictedType PredictInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses. +static const PredictedType PredictUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses. +static const PredictedType PredictUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses. +static const PredictedType PredictUint16Array = 0x00000200; // It's definitely an Uint16Array or one of its subclasses. +static const PredictedType PredictUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses. +static const PredictedType PredictFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses. +static const PredictedType PredictFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses. +static const PredictedType PredictObjectOther = 0x00002000; // It's definitely an object but not JSFinalObject, JSArray, JSByteArray, or JSFunction. +static const PredictedType PredictObjectMask = 0x00003fff; // Bitmask used for testing for any kind of object prediction. +static const PredictedType PredictString = 0x00004000; // It's definitely a JSString. +static const PredictedType PredictCellOther = 0x00008000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString. +static const PredictedType PredictCell = 0x0000ffff; // It's definitely a JSCell. +static const PredictedType PredictInt32 = 0x00010000; // It's definitely an Int32. +static const PredictedType PredictDoubleReal = 0x00020000; // It's definitely a non-NaN double. +static const PredictedType PredictDoubleNaN = 0x00040000; // It's definitely a NaN. +static const PredictedType PredictDouble = 0x00060000; // It's either a non-NaN or a NaN double. +static const PredictedType PredictNumber = 0x00070000; // It's either an Int32 or a Double. +static const PredictedType PredictBoolean = 0x00080000; // It's definitely a Boolean. +static const PredictedType PredictOther = 0x40000000; // It's definitely none of the above. +static const PredictedType PredictTop = 0x7fffffff; // It can be any of the above. +static const PredictedType FixedIndexedStorageMask = PredictByteArray | PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint8ClampedArray | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array; typedef bool (*PredictionChecker)(PredictedType); @@ -131,6 +132,11 @@ inline bool isUint8ArrayPrediction(PredictedType value) return value == PredictUint8Array; } +inline bool isUint8ClampedArrayPrediction(PredictedType value) +{ + return value == PredictUint8ClampedArray; +} + inline bool isUint16ArrayPrediction(PredictedType value) { return value == PredictUint16Array; @@ -161,6 +167,7 @@ inline bool isActionableMutableArrayPrediction(PredictedType value) #endif || isInt32ArrayPrediction(value) || isUint8ArrayPrediction(value) + || isUint8ClampedArrayPrediction(value) || isUint16ArrayPrediction(value) || isUint32ArrayPrediction(value) #if CPU(X86) || CPU(X86_64) diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp new file mode 100644 index 000000000..45a5e614c --- /dev/null +++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PutByIdStatus.h" + +#include "CodeBlock.h" +#include "Structure.h" +#include "StructureChain.h" + +namespace JSC { + +PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident) +{ + UNUSED_PARAM(profiledBlock); + UNUSED_PARAM(bytecodeIndex); + UNUSED_PARAM(ident); +#if ENABLE(JIT) && ENABLE(VALUE_PROFILER) + if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex)) + return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound); + + StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex); + if (!stubInfo.seen) + return PutByIdStatus(NoInformation, 0, 0, 0, notFound); + + switch (stubInfo.accessType) { + case access_unset: + return PutByIdStatus(NoInformation, 0, 0, 0, notFound); + + case access_put_by_id_replace: { + size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get( + *profiledBlock->globalData(), ident); + if (offset != notFound) { + return PutByIdStatus( + SimpleReplace, + stubInfo.u.putByIdReplace.baseObjectStructure.get(), + 0, 0, + offset); + } + return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound); + } + + case access_put_by_id_transition_normal: + case access_put_by_id_transition_direct: { + size_t offset = stubInfo.u.putByIdTransition.structure->get( + *profiledBlock->globalData(), ident); + if (offset != notFound) { + return PutByIdStatus( + SimpleTransition, + stubInfo.u.putByIdTransition.previousStructure.get(), + stubInfo.u.putByIdTransition.structure.get(), + stubInfo.u.putByIdTransition.chain.get(), + offset); + } + return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound); + } + + default: + return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound); + } +#else // ENABLE(JIT) + return PutByIdStatus(NoInformation, 0, 0, 0, notFound); +#endif // ENABLE(JIT) +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.h b/Source/JavaScriptCore/bytecode/PutByIdStatus.h new file mode 100644 index 000000000..b33f4d09c --- /dev/null +++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PutByIdStatus_h +#define PutByIdStatus_h + +#include <wtf/NotFound.h> + +namespace JSC { + +class CodeBlock; +class Identifier; +class Structure; +class StructureChain; + +class PutByIdStatus { +public: + enum State { + // It's uncached so we have no information. + NoInformation, + // It's cached as a direct store into an object property for cases where the object + // already has the property. + SimpleReplace, + // It's cached as a transition from one structure that lacks the property to one that + // includes the property, and a direct store to this new property. + SimpleTransition, + // It's known to often take slow path. + TakesSlowPath + }; + + PutByIdStatus() + : m_state(NoInformation) + , m_oldStructure(0) + , m_newStructure(0) + , m_structureChain(0) + , m_offset(notFound) + { + } + + PutByIdStatus( + State state, + Structure* oldStructure, + Structure* newStructure, + StructureChain* structureChain, + size_t offset) + : m_state(state) + , m_oldStructure(oldStructure) + , m_newStructure(newStructure) + , m_structureChain(structureChain) + , m_offset(offset) + { + ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == !m_oldStructure); + ASSERT((m_state != SimpleTransition) == !m_newStructure); + ASSERT((m_state != SimpleTransition) == !m_structureChain); + ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == notFound)); + } + + static PutByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&); + + State state() const { return m_state; } + + bool isSet() const { return m_state != NoInformation; } + bool operator!() const { return m_state == NoInformation; } + bool isSimpleReplace() const { return m_state == SimpleReplace; } + bool isSimpleTransition() const { return m_state == SimpleTransition; } + bool takesSlowPath() const { return m_state == TakesSlowPath; } + + Structure* oldStructure() const { return m_oldStructure; } + Structure* newStructure() const { return m_newStructure; } + StructureChain* structureChain() const { return m_structureChain; } + size_t offset() const { return m_offset; } + +private: + State m_state; + Structure* m_oldStructure; + Structure* m_newStructure; + StructureChain* m_structureChain; + size_t m_offset; +}; + +} // namespace JSC + +#endif // PutByIdStatus_h + diff --git a/Source/JavaScriptCore/bytecode/SamplingTool.h b/Source/JavaScriptCore/bytecode/SamplingTool.h index b69ef026e..32a44ad69 100644 --- a/Source/JavaScriptCore/bytecode/SamplingTool.h +++ b/Source/JavaScriptCore/bytecode/SamplingTool.h @@ -45,8 +45,8 @@ namespace JSC { class SamplingFlags { public: - static void start(); - static void stop(); + JS_EXPORT_PRIVATE static void start(); + JS_EXPORT_PRIVATE static void stop(); #if ENABLE(SAMPLING_FLAGS) static void setFlag(unsigned flag) @@ -89,7 +89,7 @@ namespace JSC { #endif private: - static uint32_t s_flags; + JS_EXPORTDATA static uint32_t s_flags; #if ENABLE(SAMPLING_FLAGS) static uint64_t s_flagCounts[33]; #endif @@ -174,7 +174,7 @@ namespace JSC { class SamplingRegion { public: SamplingRegion(const char*) { } - void dump(); + JS_EXPORT_PRIVATE void dump(); }; #endif // ENABLE(SAMPLING_REGIONS) @@ -220,8 +220,8 @@ namespace JSC { static unsigned s_hertz; static ThreadIdentifier s_samplingThread; - static void start(unsigned hertz=10000); - static void stop(); + JS_EXPORT_PRIVATE static void start(unsigned hertz=10000); + JS_EXPORT_PRIVATE static void stop(); static void* threadStartFunc(void*); }; @@ -294,7 +294,7 @@ namespace JSC { memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions)); } - void setup(); + JS_EXPORT_PRIVATE void setup(); void dump(ExecState*); void notifyOfScope(JSGlobalData&, ScriptExecutable* scope); diff --git a/Source/JavaScriptCore/bytecode/StructureSet.h b/Source/JavaScriptCore/bytecode/StructureSet.h new file mode 100644 index 000000000..344183b45 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/StructureSet.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef StructureSet_h +#define StructureSet_h + +#include "PredictedType.h" +#include <stdio.h> +#include <wtf/Vector.h> + +namespace JSC { + +class Structure; + +namespace DFG { +class StructureAbstractValue; +} + +class StructureSet { +public: + StructureSet() { } + + StructureSet(Structure* structure) + { + m_structures.append(structure); + } + + void clear() + { + m_structures.clear(); + } + + void add(Structure* structure) + { + ASSERT(!contains(structure)); + m_structures.append(structure); + } + + bool addAll(const StructureSet& other) + { + bool changed = false; + for (size_t i = 0; i < other.size(); ++i) { + if (contains(other[i])) + continue; + add(other[i]); + changed = true; + } + return changed; + } + + void remove(Structure* structure) + { + for (size_t i = 0; i < m_structures.size(); ++i) { + if (m_structures[i] != structure) + continue; + + m_structures[i] = m_structures.last(); + m_structures.removeLast(); + return; + } + } + + bool contains(Structure* structure) const + { + for (size_t i = 0; i < m_structures.size(); ++i) { + if (m_structures[i] == structure) + return true; + } + return false; + } + + bool isSubsetOf(const StructureSet& other) const + { + for (size_t i = 0; i < m_structures.size(); ++i) { + if (!other.contains(m_structures[i])) + return false; + } + return true; + } + + bool isSupersetOf(const StructureSet& other) const + { + return other.isSubsetOf(*this); + } + + size_t size() const { return m_structures.size(); } + + Structure* at(size_t i) const { return m_structures.at(i); } + + Structure* operator[](size_t i) const { return at(i); } + + Structure* last() const { return m_structures.last(); } + + PredictedType predictionFromStructures() const + { + PredictedType result = PredictNone; + + for (size_t i = 0; i < m_structures.size(); ++i) + mergePrediction(result, predictionFromStructure(m_structures[i])); + + return result; + } + + bool operator==(const StructureSet& other) const + { + if (m_structures.size() != other.m_structures.size()) + return false; + + for (size_t i = 0; i < m_structures.size(); ++i) { + if (!other.contains(m_structures[i])) + return false; + } + + return true; + } + + void dump(FILE* out) + { + fprintf(out, "["); + for (size_t i = 0; i < m_structures.size(); ++i) { + if (i) + fprintf(out, ", "); + fprintf(out, "%p", m_structures[i]); + } + fprintf(out, "]"); + } + +private: + friend class DFG::StructureAbstractValue; + + Vector<Structure*, 2> m_structures; +}; + +} // namespace JSC + +#endif // StructureSet_h diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h index 5c7ee0bb8..d6b6092d0 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h @@ -28,6 +28,7 @@ #if ENABLE(JIT) +#include "CodeOrigin.h" #include "Instruction.h" #include "MacroAssembler.h" #include "Opcode.h" @@ -175,6 +176,8 @@ namespace JSC { int8_t seen; #if ENABLE(DFG_JIT) + CodeOrigin codeOrigin; + int8_t registersFlushed; int8_t baseGPR; #if USE(JSVALUE32_64) int8_t valueTagGPR; |