Changeset 178692 in webkit for trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
- Timestamp:
- Jan 19, 2015, 8:47:55 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r178106 r178692 2137 2137 } 2138 2138 2139 if (vm()->controlFlowProfiler()) { 2140 const Vector<size_t>& bytecodeOffsets = unlinkedCodeBlock->opProfileControlFlowBytecodeOffsets(); 2141 for (size_t i = 0, offsetsLength = bytecodeOffsets.size(); i < offsetsLength; i++) { 2142 // Because op_profile_control_flow is emitted at the beginning of every basic block, finding 2143 // the next op_profile_control_flow will give us the text range of a single basic block. 2144 size_t startIdx = bytecodeOffsets[i]; 2145 RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[startIdx].u.opcode) == op_profile_control_flow); 2146 int basicBlockStartOffset = instructions[startIdx + 1].u.operand; 2147 int basicBlockEndOffset; 2148 if (i + 1 < offsetsLength) { 2149 size_t endIdx = bytecodeOffsets[i + 1]; 2150 RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[endIdx].u.opcode) == op_profile_control_flow); 2151 basicBlockEndOffset = instructions[endIdx + 1].u.operand; 2152 } else 2153 basicBlockEndOffset = m_sourceOffset + m_ownerExecutable->source().length() - 1; 2154 2155 BasicBlockLocation* basicBlockLocation = vm()->controlFlowProfiler()->getBasicBlockLocation(m_ownerExecutable->sourceID(), basicBlockStartOffset, basicBlockEndOffset); 2156 2157 // Find all functions that are enclosed within the range: [basicBlockStartOffset, basicBlockEndOffset] 2158 // and insert these functions' start/end offsets as gaps in the current BasicBlockLocation. 2159 // This is necessary because in the original source text of a JavaScript program, 2160 // function literals form new basic blocks boundaries, but they aren't represented 2161 // inside the CodeBlock's instruction stream. 2162 auto insertFunctionGaps = [basicBlockLocation, basicBlockStartOffset, basicBlockEndOffset] (const WriteBarrier<FunctionExecutable>& functionExecutable) { 2163 const UnlinkedFunctionExecutable* executable = functionExecutable->unlinkedExecutable(); 2164 int functionStart = executable->typeProfilingStartOffset(); 2165 int functionEnd = executable->typeProfilingEndOffset(); 2166 if (functionStart >= basicBlockStartOffset && functionEnd <= basicBlockEndOffset) 2167 basicBlockLocation->insertGap(functionStart, functionEnd); 2168 }; 2169 2170 for (const WriteBarrier<FunctionExecutable>& executable : m_functionDecls) 2171 insertFunctionGaps(executable); 2172 for (const WriteBarrier<FunctionExecutable>& executable : m_functionExprs) 2173 insertFunctionGaps(executable); 2174 2175 instructions[startIdx + 1].u.basicBlockLocation = basicBlockLocation; 2176 } 2177 } 2139 if (vm()->controlFlowProfiler()) 2140 insertBasicBlockBoundariesForControlFlowProfiler(instructions); 2178 2141 2179 2142 m_instructions = WTF::RefCountedArray<Instruction>(instructions); … … 4067 4030 #endif 4068 4031 4032 void CodeBlock::insertBasicBlockBoundariesForControlFlowProfiler(Vector<Instruction, 0, UnsafeVectorOverflow>& instructions) 4033 { 4034 const Vector<size_t>& bytecodeOffsets = unlinkedCodeBlock()->opProfileControlFlowBytecodeOffsets(); 4035 for (size_t i = 0, offsetsLength = bytecodeOffsets.size(); i < offsetsLength; i++) { 4036 // Because op_profile_control_flow is emitted at the beginning of every basic block, finding 4037 // the next op_profile_control_flow will give us the text range of a single basic block. 4038 size_t startIdx = bytecodeOffsets[i]; 4039 RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[startIdx].u.opcode) == op_profile_control_flow); 4040 int basicBlockStartOffset = instructions[startIdx + 1].u.operand; 4041 int basicBlockEndOffset; 4042 if (i + 1 < offsetsLength) { 4043 size_t endIdx = bytecodeOffsets[i + 1]; 4044 RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[endIdx].u.opcode) == op_profile_control_flow); 4045 basicBlockEndOffset = instructions[endIdx + 1].u.operand; 4046 } else { 4047 basicBlockEndOffset = m_sourceOffset + m_ownerExecutable->source().length() - 1; // Offset before the closing brace. 4048 basicBlockStartOffset = std::min(basicBlockStartOffset, basicBlockEndOffset); // Some start offsets may be at the closing brace, ensure it is the offset before. 4049 } 4050 4051 // The following check allows for the same textual JavaScript basic block to have its bytecode emitted more 4052 // than once and still play nice with the control flow profiler. When basicBlockStartOffset is larger than 4053 // basicBlockEndOffset, it indicates that the bytecode generator has emitted code for the same AST node 4054 // more than once (for example: ForInNode, Finally blocks in TryNode, etc). Though these are different 4055 // basic blocks at the bytecode level, they are generated from the same textual basic block in the JavaScript 4056 // program. The condition: 4057 // (basicBlockEndOffset < basicBlockStartOffset) 4058 // is encountered when op_profile_control_flow lies across the boundary of these duplicated bytecode basic 4059 // blocks and the textual offset goes from the end of the duplicated block back to the beginning. These 4060 // ranges are dummy ranges and are ignored. The duplicated bytecode basic blocks point to the same 4061 // internal data structure, so if any of them execute, it will record the same textual basic block in the 4062 // JavaScript program as executing. 4063 // At the bytecode level, this situation looks like: 4064 // j: op_profile_control_flow (from j->k, we have basicBlockEndOffset < basicBlockStartOffset) 4065 // ... 4066 // k: op_profile_control_flow (we want to skip over the j->k block and start fresh at offset k as the start of a new basic block k->m). 4067 // ... 4068 // m: op_profile_control_flow 4069 if (basicBlockEndOffset < basicBlockStartOffset) { 4070 RELEASE_ASSERT(i + 1 < offsetsLength); // We should never encounter dummy blocks at the end of a CodeBlock. 4071 instructions[startIdx + 1].u.basicBlockLocation = vm()->controlFlowProfiler()->dummyBasicBlock(); 4072 continue; 4073 } 4074 4075 BasicBlockLocation* basicBlockLocation = vm()->controlFlowProfiler()->getBasicBlockLocation(m_ownerExecutable->sourceID(), basicBlockStartOffset, basicBlockEndOffset); 4076 4077 // Find all functions that are enclosed within the range: [basicBlockStartOffset, basicBlockEndOffset] 4078 // and insert these functions' start/end offsets as gaps in the current BasicBlockLocation. 4079 // This is necessary because in the original source text of a JavaScript program, 4080 // function literals form new basic blocks boundaries, but they aren't represented 4081 // inside the CodeBlock's instruction stream. 4082 auto insertFunctionGaps = [basicBlockLocation, basicBlockStartOffset, basicBlockEndOffset] (const WriteBarrier<FunctionExecutable>& functionExecutable) { 4083 const UnlinkedFunctionExecutable* executable = functionExecutable->unlinkedExecutable(); 4084 int functionStart = executable->typeProfilingStartOffset(); 4085 int functionEnd = executable->typeProfilingEndOffset(); 4086 if (functionStart >= basicBlockStartOffset && functionEnd <= basicBlockEndOffset) 4087 basicBlockLocation->insertGap(functionStart, functionEnd); 4088 }; 4089 4090 for (const WriteBarrier<FunctionExecutable>& executable : m_functionDecls) 4091 insertFunctionGaps(executable); 4092 for (const WriteBarrier<FunctionExecutable>& executable : m_functionExprs) 4093 insertFunctionGaps(executable); 4094 4095 instructions[startIdx + 1].u.basicBlockLocation = basicBlockLocation; 4096 } 4097 } 4098 4069 4099 } // namespace JSC
Note:
See TracChangeset
for help on using the changeset viewer.