Bytecode instructions that may have value profiling should have a direct inline
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Jan 2012 20:22:18 +0000 (20:22 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Jan 2012 20:22:18 +0000 (20:22 +0000)
link to the ValueProfile instance
https://bugs.webkit.org/show_bug.cgi?id=76682
<rdar://problem/10727689>

Reviewed by Sam Weinig.

Each opcode that gets value profiled now has a link to its ValueProfile. This
required rationalizing the emission of value profiles for opcode combos, like
op_method_check/op_get_by_id and op_call/op_call_put_result. It only makes
sense for one of them to have a value profile link, and it makes most sense
for it to be the one that actually sets the result. The previous behavior was
to have op_method_check profile for op_get_by_id when they were used together,
but otherwise for op_get_by_id to have its own profiles. op_call already did
the right thing; all profiling was done by op_call_put_result.

But rationalizing this code required breaking some of the natural boundaries
that the code had; for instance the code in DFG that emits a GetById in place
of both op_method_check and op_get_by_id must now know that it's the latter of
those that has the value profile, while the first of those constitutes the OSR
target. Hence each CodeOrigin must now have two bytecode indices - one for
OSR exit and one for profiling.

Finally this change required some refiddling of our optimization heuristics,
because now all code blocks have "more instructions" due to the value profile
slots.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::dump):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::valueProfileForBytecodeOffset):
* bytecode/CodeOrigin.h:
(JSC::CodeOrigin::CodeOrigin):
(JSC::CodeOrigin::bytecodeIndexForValueProfile):
* bytecode/Instruction.h:
(JSC::Instruction::Instruction):
* bytecode/Opcode.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitProfiledOpcode):
(JSC::BytecodeGenerator::emitResolve):
(JSC::BytecodeGenerator::emitGetScopedVar):
(JSC::BytecodeGenerator::emitResolveBase):
(JSC::BytecodeGenerator::emitResolveBaseForPut):
(JSC::BytecodeGenerator::emitResolveWithBase):
(JSC::BytecodeGenerator::emitResolveWithThis):
(JSC::BytecodeGenerator::emitGetById):
(JSC::BytecodeGenerator::emitGetByVal):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitCallVarargs):
(JSC::BytecodeGenerator::emitConstruct):
* bytecompiler/BytecodeGenerator.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::ByteCodeParser):
(JSC::DFG::ByteCodeParser::currentCodeOrigin):
(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
(JSC::DFG::ByteCodeParser::getPrediction):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::parse):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::valueProfileFor):
* jit/JIT.h:
(JSC::JIT::emitValueProfilingSite):
* jit/JITCall.cpp:
(JSC::JIT::emit_op_call_put_result):
* jit/JITCall32_64.cpp:
(JSC::JIT::emit_op_call_put_result):
* jit/JITInlineMethods.h:
(JSC::JIT::emitValueProfilingSite):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_resolve):
(JSC::JIT::emit_op_resolve_base):
(JSC::JIT::emit_op_resolve_skip):
(JSC::JIT::emit_op_resolve_global):
(JSC::JIT::emitSlow_op_resolve_global):
(JSC::JIT::emit_op_resolve_with_base):
(JSC::JIT::emit_op_resolve_with_this):
(JSC::JIT::emitSlow_op_resolve_global_dynamic):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_resolve):
(JSC::JIT::emit_op_resolve_base):
(JSC::JIT::emit_op_resolve_skip):
(JSC::JIT::emit_op_resolve_global):
(JSC::JIT::emitSlow_op_resolve_global):
(JSC::JIT::emit_op_resolve_with_base):
(JSC::JIT::emit_op_resolve_with_this):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_method_check):
(JSC::JIT::emitSlow_op_method_check):
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id):
(JSC::JIT::emit_op_get_scoped_var):
(JSC::JIT::emit_op_get_global_var):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_method_check):
(JSC::JIT::emitSlow_op_method_check):
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id):
(JSC::JIT::emit_op_get_scoped_var):
(JSC::JIT::emit_op_get_global_var):
* jit/JITStubCall.h:
(JSC::JITStubCall::callWithValueProfiling):
* runtime/Options.cpp:
(JSC::Options::initializeOptions):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@105533 268f45cc-cd09-0410-ab3c-d52691b4dbfc

20 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/CodeOrigin.h
Source/JavaScriptCore/bytecode/Instruction.h
Source/JavaScriptCore/bytecode/Opcode.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITCall.cpp
Source/JavaScriptCore/jit/JITCall32_64.cpp
Source/JavaScriptCore/jit/JITInlineMethods.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
Source/JavaScriptCore/jit/JITStubCall.h
Source/JavaScriptCore/runtime/Options.cpp

index 09dcea5..28b15cf 100644 (file)
@@ -1,3 +1,117 @@
+2012-01-19  Filip Pizlo  <fpizlo@apple.com>
+
+        Bytecode instructions that may have value profiling should have a direct inline
+        link to the ValueProfile instance
+        https://bugs.webkit.org/show_bug.cgi?id=76682
+        <rdar://problem/10727689>
+
+        Reviewed by Sam Weinig.
+        
+        Each opcode that gets value profiled now has a link to its ValueProfile. This
+        required rationalizing the emission of value profiles for opcode combos, like
+        op_method_check/op_get_by_id and op_call/op_call_put_result. It only makes
+        sense for one of them to have a value profile link, and it makes most sense
+        for it to be the one that actually sets the result. The previous behavior was
+        to have op_method_check profile for op_get_by_id when they were used together,
+        but otherwise for op_get_by_id to have its own profiles. op_call already did
+        the right thing; all profiling was done by op_call_put_result.
+        
+        But rationalizing this code required breaking some of the natural boundaries
+        that the code had; for instance the code in DFG that emits a GetById in place
+        of both op_method_check and op_get_by_id must now know that it's the latter of
+        those that has the value profile, while the first of those constitutes the OSR
+        target. Hence each CodeOrigin must now have two bytecode indices - one for
+        OSR exit and one for profiling.
+        
+        Finally this change required some refiddling of our optimization heuristics,
+        because now all code blocks have "more instructions" due to the value profile
+        slots.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::printGetByIdOp):
+        (JSC::CodeBlock::dump):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::valueProfileForBytecodeOffset):
+        * bytecode/CodeOrigin.h:
+        (JSC::CodeOrigin::CodeOrigin):
+        (JSC::CodeOrigin::bytecodeIndexForValueProfile):
+        * bytecode/Instruction.h:
+        (JSC::Instruction::Instruction):
+        * bytecode/Opcode.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitProfiledOpcode):
+        (JSC::BytecodeGenerator::emitResolve):
+        (JSC::BytecodeGenerator::emitGetScopedVar):
+        (JSC::BytecodeGenerator::emitResolveBase):
+        (JSC::BytecodeGenerator::emitResolveBaseForPut):
+        (JSC::BytecodeGenerator::emitResolveWithBase):
+        (JSC::BytecodeGenerator::emitResolveWithThis):
+        (JSC::BytecodeGenerator::emitGetById):
+        (JSC::BytecodeGenerator::emitGetByVal):
+        (JSC::BytecodeGenerator::emitCall):
+        (JSC::BytecodeGenerator::emitCallVarargs):
+        (JSC::BytecodeGenerator::emitConstruct):
+        * bytecompiler/BytecodeGenerator.h:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::ByteCodeParser):
+        (JSC::DFG::ByteCodeParser::currentCodeOrigin):
+        (JSC::DFG::ByteCodeParser::addCall):
+        (JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
+        (JSC::DFG::ByteCodeParser::getPrediction):
+        (JSC::DFG::ByteCodeParser::handleCall):
+        (JSC::DFG::ByteCodeParser::handleInlining):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        (JSC::DFG::ByteCodeParser::parse):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::valueProfileFor):
+        * jit/JIT.h:
+        (JSC::JIT::emitValueProfilingSite):
+        * jit/JITCall.cpp:
+        (JSC::JIT::emit_op_call_put_result):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::emit_op_call_put_result):
+        * jit/JITInlineMethods.h:
+        (JSC::JIT::emitValueProfilingSite):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_resolve):
+        (JSC::JIT::emit_op_resolve_base):
+        (JSC::JIT::emit_op_resolve_skip):
+        (JSC::JIT::emit_op_resolve_global):
+        (JSC::JIT::emitSlow_op_resolve_global):
+        (JSC::JIT::emit_op_resolve_with_base):
+        (JSC::JIT::emit_op_resolve_with_this):
+        (JSC::JIT::emitSlow_op_resolve_global_dynamic):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_resolve):
+        (JSC::JIT::emit_op_resolve_base):
+        (JSC::JIT::emit_op_resolve_skip):
+        (JSC::JIT::emit_op_resolve_global):
+        (JSC::JIT::emitSlow_op_resolve_global):
+        (JSC::JIT::emit_op_resolve_with_base):
+        (JSC::JIT::emit_op_resolve_with_this):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_get_by_val):
+        (JSC::JIT::emitSlow_op_get_by_val):
+        (JSC::JIT::emit_op_method_check):
+        (JSC::JIT::emitSlow_op_method_check):
+        (JSC::JIT::emit_op_get_by_id):
+        (JSC::JIT::emitSlow_op_get_by_id):
+        (JSC::JIT::emit_op_get_scoped_var):
+        (JSC::JIT::emit_op_get_global_var):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_method_check):
+        (JSC::JIT::emitSlow_op_method_check):
+        (JSC::JIT::emit_op_get_by_val):
+        (JSC::JIT::emitSlow_op_get_by_val):
+        (JSC::JIT::emit_op_get_by_id):
+        (JSC::JIT::emitSlow_op_get_by_id):
+        (JSC::JIT::emit_op_get_scoped_var):
+        (JSC::JIT::emit_op_get_global_var):
+        * jit/JITStubCall.h:
+        (JSC::JITStubCall::callWithValueProfiling):
+        * runtime/Options.cpp:
+        (JSC::Options::initializeOptions):
+
 2012-01-20  ChangSeok Oh  <shivamidow@gmail.com>
 
         undefined reference to symbol eina_module_free
index 8f283d8..72ea0b4 100644 (file)
@@ -180,7 +180,7 @@ 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
@@ -743,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: {
@@ -750,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: {
@@ -766,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: {
@@ -773,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: {
@@ -786,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: {
@@ -799,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: {
@@ -812,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: {
@@ -819,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: {
@@ -924,6 +932,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: {
@@ -1162,6 +1171,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: {
index ceb7be6..bc30050 100644 (file)
@@ -521,6 +521,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;
         }
         
index 7b6ce7d..25a116c 100644 (file)
@@ -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;
index 5e628c0..92118ee 100644 (file)
@@ -48,6 +48,7 @@ namespace JSC {
     class JSCell;
     class Structure;
     class StructureChain;
+    struct ValueProfile;
 
 #if ENABLE(JIT)
     typedef MacroAssemblerCodeRef PolymorphicAccessStructureListStubRoutineType;
@@ -180,6 +181,8 @@ namespace JSC {
         }
 
         Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
+        
+        Instruction(ValueProfile* profile) { u.profile = profile; }
 
         union {
             Opcode opcode;
@@ -188,6 +191,7 @@ namespace JSC {
             WriteBarrierBase<StructureChain> structureChain;
             WriteBarrierBase<JSCell> jsCell;
             PropertySlot::GetValueFunc getterFunc;
+            ValueProfile* profile;
         } u;
         
     private:
index 4801e4c..0f94176 100644 (file)
@@ -95,38 +95,38 @@ 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_by_val, 5) /* has value profiling */ \
         macro(op_get_argument_by_val, 4) \
         macro(op_get_by_pname, 7) \
         macro(op_put_by_val, 4) \
@@ -170,7 +170,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) \
         \
index bfb1618..32e8b1a 100644 (file)
@@ -668,6 +668,13 @@ void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
     m_lastOpcodeID = opcodeID;
 }
 
+ValueProfile* BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
+{
+    ValueProfile* result = m_codeBlock->addValueProfile(instructions().size());
+    emitOpcode(opcodeID);
+    return result;
+}
+
 void BytecodeGenerator::emitLoopHint()
 {
 #if ENABLE(DFG_JIT)
@@ -1245,9 +1252,10 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
     bool requiresDynamicChecks = false;
     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) && !globalObject) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return dst;
     }
     if (shouldAvoidResolveGlobal()) {
@@ -1267,21 +1275,23 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
 #if ENABLE(INTERPRETER)
         m_codeBlock->addGlobalResolveInstruction(instructions().size());
 #endif
-        emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
+        ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(0);
         instructions().append(0);
         if (requiresDynamicChecks)
             instructions().append(depth);
+        instructions().append(profile);
         return dst;
     }
 
     if (requiresDynamicChecks) {
         // If we get here we have eval nested inside a |with| just give up
-        emitOpcode(op_resolve);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return dst;
     }
 
@@ -1292,10 +1302,11 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
 
     // In this case we are at least able to drop a few scope chains from the
     // lookup chain, although we still need to hash from then on.
-    emitOpcode(op_resolve_skip);
+    ValueProfile* profile = emitProfiledOpcode(op_resolve_skip);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
     instructions().append(depth);
+    instructions().append(profile);
     return dst;
 }
 
@@ -1311,16 +1322,18 @@ RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, i
                 return dst;
         }
 
-        emitOpcode(op_get_global_var);
+        ValueProfile* profile = emitProfiledOpcode(op_get_global_var);
         instructions().append(dst->index());
         instructions().append(index);
+        instructions().append(profile);
         return dst;
     }
 
-    emitOpcode(op_get_scoped_var);
+    ValueProfile* profile = emitProfiledOpcode(op_get_scoped_var);
     instructions().append(dst->index());
     instructions().append(index);
     instructions().append(depth);
+    instructions().append(profile);
     return dst;
 }
 
@@ -1348,10 +1361,11 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier
     findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
     if (!globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve_base);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(false);
+        instructions().append(profile);
         return dst;
     }
 
@@ -1370,10 +1384,11 @@ RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Iden
     findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
     if (!globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve_base);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(true);
+        instructions().append(profile);
         return dst;
     }
     
@@ -1393,10 +1408,11 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
     bool requiresDynamicChecks = false;
     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve_with_base);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
         instructions().append(baseDst->index());
         instructions().append(propDst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return baseDst;
     }
 
@@ -1411,9 +1427,10 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
         return baseDst;
     }
     if (shouldAvoidResolveGlobal()) {
-        emitOpcode(op_resolve);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve);
         instructions().append(propDst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return baseDst;
     }
 #if ENABLE(JIT)
@@ -1422,13 +1439,14 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
 #if ENABLE(INTERPRETER)
     m_codeBlock->addGlobalResolveInstruction(instructions().size());
 #endif
-    emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
+    ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
     instructions().append(propDst->index());
     instructions().append(addConstant(property));
     instructions().append(0);
     instructions().append(0);
     if (requiresDynamicChecks)
         instructions().append(depth);
+    instructions().append(profile);
     return baseDst;
 }
 
@@ -1440,10 +1458,11 @@ RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, Register
     bool requiresDynamicChecks = false;
     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve_with_this);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve_with_this);
         instructions().append(baseDst->index());
         instructions().append(propDst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return baseDst;
     }
 
@@ -1458,9 +1477,10 @@ RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, Register
         return baseDst;
     }
     if (shouldAvoidResolveGlobal()) {
-        emitOpcode(op_resolve);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve);
         instructions().append(propDst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return baseDst;
     }
 #if ENABLE(JIT)
@@ -1469,13 +1489,14 @@ RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, Register
 #if ENABLE(INTERPRETER)
     m_codeBlock->addGlobalResolveInstruction(instructions().size());
 #endif
-    emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
+    ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
     instructions().append(propDst->index());
     instructions().append(addConstant(property));
     instructions().append(0);
     instructions().append(0);
     if (requiresDynamicChecks)
         instructions().append(depth);
+    instructions().append(profile);
     return baseDst;
 }
 
@@ -1490,7 +1511,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 
-    emitOpcode(op_get_by_id);
+    ValueProfile* profile = emitProfiledOpcode(op_get_by_id);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(addConstant(property));
@@ -1498,6 +1519,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
     instructions().append(0);
     instructions().append(0);
     instructions().append(0);
+    instructions().append(profile);
     return dst;
 }
 
@@ -1599,10 +1621,11 @@ RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, R
             return dst;
         }
     }
-    emitOpcode(op_get_by_val);
+    ValueProfile* profile = emitProfiledOpcode(op_get_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(property->index());
+    instructions().append(profile);
     return dst;
 }
 
@@ -1824,8 +1847,9 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     instructions().append(0);
     instructions().append(0);
     if (dst != ignoredResult()) {
-        emitOpcode(op_call_put_result);
+        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
+        instructions().append(profile);
     }
 
     if (m_shouldEmitProfileHooks) {
@@ -1853,8 +1877,9 @@ RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func
     instructions().append(arguments->index());
     instructions().append(firstFreeRegister->index());
     if (dst != ignoredResult()) {
-        emitOpcode(op_call_put_result);
+        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
         instructions().append(dst->index());
+        instructions().append(profile);
     }
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_did_call);
@@ -1926,8 +1951,9 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
     instructions().append(0);
     instructions().append(0);
     if (dst != ignoredResult()) {
-        emitOpcode(op_call_put_result);
+        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
+        instructions().append(profile);
     }
 
     if (m_shouldEmitProfileHooks) {
index ce8d8f8..59d776e 100644 (file)
@@ -409,6 +409,7 @@ namespace JSC {
 
     private:
         void emitOpcode(OpcodeID);
+        ValueProfile* emitProfiledOpcode(OpcodeID);
         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
         void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
         ALWAYS_INLINE void rewindBinaryOp();
index 21aa621..51a8a0c 100644 (file)
@@ -48,6 +48,7 @@ public:
         , m_graph(graph)
         , m_currentBlock(0)
         , m_currentIndex(0)
+        , m_currentProfilingIndex(0)
         , m_constantUndefined(UINT_MAX)
         , m_constantNull(UINT_MAX)
         , m_constantNaN(UINT_MAX)
@@ -519,7 +520,7 @@ private:
     
     CodeOrigin currentCodeOrigin()
     {
-        return CodeOrigin(m_currentIndex, m_inlineStackTop->m_inlineCallFrame);
+        return CodeOrigin(m_currentIndex, m_inlineStackTop->m_inlineCallFrame, m_currentProfilingIndex - m_currentIndex);
     }
 
     // These methods create a node and add it to the graph. If nodes of this type are
@@ -574,8 +575,10 @@ private:
         Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
 
         PredictedType prediction = PredictNone;
-        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
-            prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
+        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
+            m_currentProfilingIndex = m_currentIndex + OPCODE_LENGTH(op_call);
+            prediction = getPrediction();
+        }
         
         addVarArgChild(get(currentInstruction[1].u.operand));
         int argCount = currentInstruction[2].u.operand;
@@ -622,12 +625,12 @@ private:
     
     PredictedType getPredictionWithoutOSRExit()
     {
-        return getPredictionWithoutOSRExit(m_graph.size(), m_currentIndex);
+        return getPredictionWithoutOSRExit(m_graph.size(), m_currentProfilingIndex);
     }
     
     PredictedType getPrediction()
     {
-        return getPrediction(m_graph.size(), m_currentIndex);
+        return getPrediction(m_graph.size(), m_currentProfilingIndex);
     }
 
     NodeIndex makeSafe(NodeIndex nodeIndex)
@@ -750,6 +753,8 @@ private:
     BasicBlock* m_currentBlock;
     // The bytecode index of the current instruction being generated.
     unsigned m_currentIndex;
+    // The bytecode index of the value profile of the current instruction being generated.
+    unsigned m_currentProfilingIndex;
 
     // We use these values during code generation, and to avoid the need for
     // special handling we make sure they are available as constants in the
@@ -945,7 +950,8 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
         if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
             resultOperand = putInstruction[1].u.operand;
             usesResult = true;
-            prediction = getPrediction(m_graph.size(), nextOffset);
+            m_currentProfilingIndex = nextOffset;
+            prediction = getPrediction();
             nextOffset += OPCODE_LENGTH(op_call_put_result);
         }
         JSFunction* expectedFunction;
@@ -1067,13 +1073,16 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
     
     // This is where the actual inlining really happens.
     unsigned oldIndex = m_currentIndex;
+    unsigned oldProfilingIndex = m_currentProfilingIndex;
     m_currentIndex = 0;
+    m_currentProfilingIndex = 0;
 
     addToGraph(InlineStart);
     
     parseCodeBlock();
     
     m_currentIndex = oldIndex;
+    m_currentProfilingIndex = oldProfilingIndex;
     
     // If the inlined code created some new basic blocks, then we have linking to do.
     if (inlineStackEntry.m_callsiteBlockHead != m_graph.m_blocks.size() - 1) {
@@ -1331,6 +1340,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
     }
 
     while (true) {
+        m_currentProfilingIndex = m_currentIndex;
+
         // Don't extend over jump destinations.
         if (m_currentIndex == limit) {
             // Ordinarily we want to plant a jump. But refuse to do this if the block is
@@ -1703,6 +1714,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
             
         case op_method_check: {
+            m_currentProfilingIndex += OPCODE_LENGTH(op_method_check);
             Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
             
             PredictedType prediction = getPrediction();
@@ -2643,6 +2655,9 @@ bool ByteCodeParser::parse()
 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
     printf("Processing local variable phis.\n");
 #endif
+    
+    m_currentProfilingIndex = m_currentIndex;
+    
     processPhiStack<LocalPhiStack>();
 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
     printf("Processing argument phis.\n");
index fb72906..df514a5 100644 (file)
@@ -223,8 +223,7 @@ public:
         
         Node& node = at(nodeIndex);
         
-        switch (node.op) {
-        case GetLocal: {
+        if (node.op == GetLocal) {
             if (!operandIsArgument(node.local()))
                 return 0;
             int argument = operandToArgument(node.local());
@@ -233,21 +232,10 @@ public:
             return profiledBlock->valueProfileForArgument(argument);
         }
         
-        // Nodes derives from calls need special handling because the value profile is
-        // associated with the op_call_put_result instruction.
-        case Call:
-        case Construct:
-        case ArrayPop:
-        case ArrayPush: {
-            ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
-            return profiledBlock->valueProfileForBytecodeOffset(node.codeOrigin.bytecodeIndex + OPCODE_LENGTH(op_call));
-        }
-
-        default:
-            if (node.hasHeapPrediction())
-                return profiledBlock->valueProfileForBytecodeOffset(node.codeOrigin.bytecodeIndex);
-            return 0;
-        }
+        if (node.hasHeapPrediction())
+            return profiledBlock->valueProfileForBytecodeOffset(node.codeOrigin.bytecodeIndexForValueProfile());
+        
+        return 0;
     }
 
     Vector< OwnPtr<BasicBlock> , 8> m_blocks;
index 750b9d8..2aec542 100644 (file)
@@ -333,14 +333,14 @@ namespace JSC {
         template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
         void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr);
         
-        enum ValueProfilingSiteKind { FirstProfilingSite, SubsequentProfilingSite };
 #if ENABLE(VALUE_PROFILER)
         // This assumes that the value to profile is in regT0 and that regT3 is available for
         // scratch.
         void emitValueProfilingSite(ValueProfile*);
-        void emitValueProfilingSite(ValueProfilingSiteKind);
+        void emitValueProfilingSite(unsigned bytecodeOffset);
+        void emitValueProfilingSite();
 #else
-        void emitValueProfilingSite(ValueProfilingSiteKind) { }
+        void emitValueProfilingSite() { }
 #endif
 
 #if USE(JSVALUE32_64)
index 465f1ad..3aeef95 100644 (file)
@@ -50,7 +50,7 @@ namespace JSC {
 void JIT::emit_op_call_put_result(Instruction* instruction)
 {
     int dst = instruction[1].u.operand;
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitPutVirtualRegister(dst);
 }
 
index 01c9db0..b84ad1a 100644 (file)
@@ -50,7 +50,7 @@ namespace JSC {
 void JIT::emit_op_call_put_result(Instruction* instruction)
 {
     int dst = instruction[1].u.operand;
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
 }
 
index 5540ffa..e617961 100644 (file)
@@ -486,20 +486,16 @@ inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile)
 #endif
 }
 
-inline void JIT::emitValueProfilingSite(ValueProfilingSiteKind siteKind)
+inline void JIT::emitValueProfilingSite(unsigned bytecodeOffset)
 {
     if (!shouldEmitProfiling())
         return;
-    
-    ValueProfile* valueProfile;
-    if (siteKind == FirstProfilingSite)
-        valueProfile = m_codeBlock->addValueProfile(m_bytecodeOffset);
-    else {
-        ASSERT(siteKind == SubsequentProfilingSite);
-        valueProfile = m_codeBlock->valueProfileForBytecodeOffset(m_bytecodeOffset);
-    }
-    
-    emitValueProfilingSite(valueProfile);
+    emitValueProfilingSite(m_codeBlock->valueProfileForBytecodeOffset(bytecodeOffset));
+}
+
+inline void JIT::emitValueProfilingSite()
+{
+    emitValueProfilingSite(m_bytecodeOffset);
 }
 #endif
 
index f5be279..4f57f4a 100644 (file)
@@ -568,7 +568,7 @@ void JIT::emit_op_resolve(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
@@ -599,7 +599,7 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction)
@@ -615,7 +615,7 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
     JITStubCall stubCall(this, cti_op_resolve_skip);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
-    stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
@@ -636,7 +636,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT0);
     load32(Address(regT2, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT1);
     loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0);
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
@@ -652,7 +652,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo
     stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.addArgument(Imm32(currentIndex));
     stubCall.addArgument(regT0);
-    stubCall.callWithValueProfiling(dst, SubsequentProfilingSite);
+    stubCall.callWithValueProfiling(dst);
 }
 
 void JIT::emit_op_not(Instruction* currentInstruction)
@@ -773,7 +773,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
     JITStubCall stubCall(this, cti_op_resolve_with_base);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
-    stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
@@ -781,7 +781,7 @@ void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
     JITStubCall stubCall(this, cti_op_resolve_with_this);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
-    stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_jtrue(Instruction* currentInstruction)
@@ -1563,7 +1563,7 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve
     stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.addArgument(Imm32(currentIndex));
     stubCall.addArgument(regT0);
-    stubCall.callWithValueProfiling(dst, SubsequentProfilingSite); // The first profiling site is in emit_op_resolve_global
+    stubCall.callWithValueProfiling(dst);
 }
 
 void JIT::emit_op_new_regexp(Instruction* currentInstruction)
index 9d1cbce..b798965 100644 (file)
@@ -660,7 +660,7 @@ void JIT::emit_op_resolve(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
@@ -702,7 +702,7 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction)
@@ -718,7 +718,7 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
     JITStubCall stubCall(this, cti_op_resolve_skip);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
-    stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
@@ -743,7 +743,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
     load32(Address(regT3, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT3);
     load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
     load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + (dynamic ? OPCODE_LENGTH(op_resolve_global_dynamic) : OPCODE_LENGTH(op_resolve_global)), dst, regT1, regT0);
 }
@@ -759,7 +759,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo
     JITStubCall stubCall(this, cti_op_resolve_global);
     stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.addArgument(Imm32(currentIndex));
-    stubCall.callWithValueProfiling(dst, SubsequentProfilingSite);
+    stubCall.callWithValueProfiling(dst);
 }
 
 void JIT::emit_op_not(Instruction* currentInstruction)
@@ -1157,7 +1157,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
     JITStubCall stubCall(this, cti_op_resolve_with_base);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
-    stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
@@ -1165,7 +1165,7 @@ void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
     JITStubCall stubCall(this, cti_op_resolve_with_this);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
-    stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite);
+    stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_throw(Instruction* currentInstruction)
index 48951e8..1deeefd 100644 (file)
@@ -116,7 +116,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0);
     addSlowCase(branchTestPtr(Zero, regT0));
 
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitPutVirtualRegister(dst);
 }
 
@@ -147,7 +147,7 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
     stubCall.addArgument(property, regT2);
     stubCall.call(dst);
 
-    emitValueProfilingSite(SubsequentProfilingSite);
+    emitValueProfilingSite();
 }
 
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch)
@@ -332,7 +332,7 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     compileGetByIdHotPath(baseVReg, ident);
 
     match.link(this);
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
     emitPutVirtualRegister(resultVReg);
 
     // We've already generated the following get_by_id, so make sure it's skipped over.
@@ -347,7 +347,7 @@ void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowC
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
 
     compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, true);
-    emitValueProfilingSite(SubsequentProfilingSite);
+    emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
 
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
@@ -361,7 +361,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
 
     emitGetVirtualRegister(baseVReg, regT0);
     compileGetByIdHotPath(baseVReg, ident);
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitPutVirtualRegister(resultVReg);
 }
 
@@ -405,7 +405,7 @@ void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCase
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
 
     compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, false);
-    emitValueProfilingSite(SubsequentProfilingSite);
+    emitValueProfilingSite();
 }
 
 void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
@@ -994,7 +994,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
     loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
     loadPtr(Address(regT0, JSVariableObject::offsetOfRegisters()), regT0);
     loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
@@ -1029,7 +1029,7 @@ void JIT::emit_op_get_global_var(Instruction* currentInstruction)
     JSVariableObject* globalObject = m_codeBlock->globalObject();
     loadPtr(&globalObject->m_registers, regT0);
     loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
index b73d7ab..bbad000 100644 (file)
@@ -144,7 +144,7 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     compileGetByIdHotPath();
     
     match.link(this);
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
     
@@ -161,7 +161,7 @@ void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowC
     int ident = currentInstruction[3].u.operand;
     
     compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter, true);
-    emitValueProfilingSite(SubsequentProfilingSite);
+    emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
     
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
@@ -228,7 +228,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
     addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
     
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
 }
@@ -261,7 +261,7 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
     stubCall.addArgument(property);
     stubCall.call(dst);
 
-    emitValueProfilingSite(SubsequentProfilingSite);
+    emitValueProfilingSite();
 }
 
 void JIT::emit_op_put_by_val(Instruction* currentInstruction)
@@ -325,7 +325,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
     emitLoad(base, regT1, regT0);
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     compileGetByIdHotPath();
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
 }
@@ -369,7 +369,7 @@ void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCase
     int ident = currentInstruction[3].u.operand;
     
     compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter);
-    emitValueProfilingSite(SubsequentProfilingSite);
+    emitValueProfilingSite();
 }
 
 void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
@@ -1043,7 +1043,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
     loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
 
     emitLoad(index, regT1, regT0, regT2);
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_scoped_var), dst, regT1, regT0);
 }
@@ -1085,7 +1085,7 @@ void JIT::emit_op_get_global_var(Instruction* currentInstruction)
     loadPtr(&globalObject->m_registers, regT2);
 
     emitLoad(index, regT1, regT0, regT2);
-    emitValueProfilingSite(FirstProfilingSite);
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
 }
index 18441c3..51401a7 100644 (file)
@@ -201,14 +201,14 @@ namespace JSC {
             return call;
         }
         
-        JIT::Call callWithValueProfiling(unsigned dst, JIT::ValueProfilingSiteKind kind)
+        JIT::Call callWithValueProfiling(unsigned dst)
         {
             ASSERT(m_returnType == Value || m_returnType == Cell);
             JIT::Call call = this->call();
             ASSERT(JIT::returnValueRegister == JIT::regT0);
             if (m_returnType == Cell)
                 m_jit->move(JIT::TrustedImm32(JSValue::CellTag), JIT::regT1);
-            m_jit->emitValueProfilingSite(kind);
+            m_jit->emitValueProfilingSite();
             if (m_returnType == Value)
                 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
             else
@@ -224,12 +224,12 @@ namespace JSC {
             return call;
         }
         
-        JIT::Call callWithValueProfiling(unsigned dst, JIT::ValueProfilingSiteKind kind)
+        JIT::Call callWithValueProfiling(unsigned dst)
         {
             ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
             JIT::Call call = this->call();
             ASSERT(JIT::returnValueRegister == JIT::regT0);
-            m_jit->emitValueProfilingSite(kind);
+            m_jit->emitValueProfilingSite();
             m_jit->emitPutVirtualRegister(dst);
             return call;
         }
index f660c87..ddfba6e 100644 (file)
@@ -130,10 +130,10 @@ void setHeuristic(T& variable, const char* name, U value)
 
 void initializeOptions()
 {
-    SET(maximumOptimizationCandidateInstructionCount, 1000);
+    SET(maximumOptimizationCandidateInstructionCount, 1100);
     
-    SET(maximumFunctionForCallInlineCandidateInstructionCount, 150);
-    SET(maximumFunctionForConstructInlineCandidateInstructionCount, 80);
+    SET(maximumFunctionForCallInlineCandidateInstructionCount, 180);
+    SET(maximumFunctionForConstructInlineCandidateInstructionCount, 100);
     
     SET(maximumInliningDepth, 5);