Changeset 39071 in webkit for trunk/JavaScriptCore
- Timestamp:
- Dec 6, 2008, 2:19:22 PM (16 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 8 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r39070 r39071 1 2008-12-06 Sam Weinig <[email protected]> 2 3 Reviewed by Cameron Zwarich. 4 5 Split JumpTable code into its own file. 6 7 * GNUmakefile.am: 8 * JavaScriptCore.pri: 9 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: 10 * JavaScriptCore.xcodeproj/project.pbxproj: 11 * JavaScriptCoreSources.bkl: 12 * bytecode/CodeBlock.cpp: 13 * bytecode/CodeBlock.h: 14 * bytecode/JumpTable.cpp: Copied from bytecode/CodeBlock.cpp. 15 * bytecode/JumpTable.h: Copied from bytecode/CodeBlock.h. 16 1 17 2008-12-05 Sam Weinig <[email protected]> 2 18 -
trunk/JavaScriptCore/GNUmakefile.am
r38992 r39071 82 82 JavaScriptCore/bytecode/CodeBlock.cpp \ 83 83 JavaScriptCore/bytecode/CodeBlock.h \ 84 JavaScriptCore/bytecode/JumpTable.cpp \ 85 JavaScriptCore/bytecode/JumpTable.h \ 84 86 JavaScriptCore/bytecode/EvalCodeCache.h \ 85 87 JavaScriptCore/runtime/ExceptionHelpers.cpp \ -
trunk/JavaScriptCore/JavaScriptCore.pri
r39034 r39071 70 70 runtime/JSNotAnObject.cpp \ 71 71 bytecode/CodeBlock.cpp \ 72 bytecode/JumpTable.cpp \ 72 73 jit/JIT.cpp \ 73 74 jit/JITCall.cpp \ -
trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
r38992 r39071 1243 1243 </File> 1244 1244 <File 1245 RelativePath="..\..\bytecode\JumpTable.cpp" 1246 > 1247 </File> 1248 <File 1249 RelativePath="..\..\bytecode\JumpTable.h" 1250 > 1251 </File> 1252 <File 1245 1253 RelativePath="..\..\jit\JIT.cpp" 1246 1254 > -
trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r39062 r39071 313 313 BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCDE3AB00E6C82CF001453A7 /* Structure.cpp */; }; 314 314 BCF605140E203EF800B9A64D /* ArgList.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF605120E203EF800B9A64D /* ArgList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 315 BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCFD8C900EEB2EE700283848 /* JumpTable.cpp */; }; 316 BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; }; 315 317 C0A272630E50A06300E96E15 /* NotFound.h in Headers */ = {isa = PBXBuildFile; fileRef = C0A2723F0E509F1E00E96E15 /* NotFound.h */; settings = {ATTRIBUTES = (Private, ); }; }; 316 318 E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 719 721 BCF605120E203EF800B9A64D /* ArgList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgList.h; sourceTree = "<group>"; }; 720 722 BCF6553B0A2048DE0038A194 /* MathExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MathExtras.h; sourceTree = "<group>"; }; 723 BCFD8C900EEB2EE700283848 /* JumpTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JumpTable.cpp; sourceTree = "<group>"; }; 724 BCFD8C910EEB2EE700283848 /* JumpTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JumpTable.h; sourceTree = "<group>"; }; 721 725 C0A2723F0E509F1E00E96E15 /* NotFound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotFound.h; sourceTree = "<group>"; }; 722 726 D21202280AD4310C00ED79B6 /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; }; … … 1384 1388 969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */, 1385 1389 969A07930ED1D3AE00F1F681 /* Instruction.h */, 1390 BCFD8C900EEB2EE700283848 /* JumpTable.cpp */, 1391 BCFD8C910EEB2EE700283848 /* JumpTable.h */, 1386 1392 969A07940ED1D3AE00F1F681 /* Opcode.cpp */, 1387 1393 969A07950ED1D3AE00F1F681 /* Opcode.h */, … … 1638 1644 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */, 1639 1645 86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */, 1646 BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */, 1640 1647 ); 1641 1648 runOnlyForDeploymentPostprocessing = 0; … … 1980 1987 86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */, 1981 1988 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */, 1989 BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */, 1982 1990 ); 1983 1991 runOnlyForDeploymentPostprocessing = 0; -
trunk/JavaScriptCore/JavaScriptCoreSources.bkl
r38536 r39071 148 148 <set append="1" var="JSCORE_VM_SOURCES"> 149 149 bytecode/CodeBlock.cpp 150 bytecode/JumpTable.cpp 150 151 runtime/ExceptionHelpers.cpp 151 152 interpreter/Interpreter.cpp -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r39070 r39071 1206 1206 } 1207 1207 1208 int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset)1209 {1210 if (value >= min && static_cast<uint32_t>(value - min) < branchOffsets.size()) {1211 int32_t offset = branchOffsets[value - min];1212 if (offset)1213 return offset;1214 }1215 return defaultOffset;1216 }1217 1218 1208 } // namespace JSC -
trunk/JavaScriptCore/bytecode/CodeBlock.h
r39070 r39071 34 34 #include "Instruction.h" 35 35 #include "JSGlobalObject.h" 36 #include "JumpTable.h" 36 37 #include "Nodes.h" 37 38 #include "RegExp.h" … … 70 71 uint32_t instructionOffset; 71 72 int32_t lineNumber; 72 };73 74 struct OffsetLocation {75 int32_t branchOffset;76 #if ENABLE(JIT)77 void* ctiOffset;78 #endif79 73 }; 80 74 … … 162 156 } 163 157 164 struct StringJumpTable {165 typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable;166 StringOffsetTable offsetTable;167 #if ENABLE(JIT)168 void* ctiDefault; // FIXME: it should not be necessary to store this.169 #endif170 171 inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset)172 {173 StringOffsetTable::const_iterator end = offsetTable.end();174 StringOffsetTable::const_iterator loc = offsetTable.find(value);175 if (loc == end)176 return defaultOffset;177 return loc->second.branchOffset;178 }179 180 #if ENABLE(JIT)181 inline void* ctiForValue(UString::Rep* value)182 {183 StringOffsetTable::const_iterator end = offsetTable.end();184 StringOffsetTable::const_iterator loc = offsetTable.find(value);185 if (loc == end)186 return ctiDefault;187 return loc->second.ctiOffset;188 }189 #endif190 };191 192 struct SimpleJumpTable {193 // FIXME: The two Vectors can be combind into one Vector<OffsetLocation>194 Vector<int32_t> branchOffsets;195 int32_t min;196 #if ENABLE(JIT)197 Vector<void*> ctiOffsets;198 void* ctiDefault;199 #endif200 201 int32_t offsetForValue(int32_t value, int32_t defaultOffset);202 void add(int32_t key, int32_t offset)203 {204 if (!branchOffsets[key])205 branchOffsets[key] = offset;206 }207 208 #if ENABLE(JIT)209 inline void* ctiForValue(int32_t value)210 {211 if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size())212 return ctiOffsets[value - min];213 return ctiDefault;214 }215 #endif216 };217 218 158 class CodeBlock { 219 159 friend class JIT; -
trunk/JavaScriptCore/bytecode/JumpTable.cpp
r39070 r39071 29 29 30 30 #include "config.h" 31 #include "CodeBlock.h" 32 33 #include "JIT.h" 34 #include "JSValue.h" 35 #include "Interpreter.h" 36 #include "Debugger.h" 37 #include <stdio.h> 38 #include <wtf/StringExtras.h> 31 #include "JumpTable.h" 39 32 40 33 namespace JSC { 41 42 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)43 44 static UString escapeQuotes(const UString& str)45 {46 UString result = str;47 int pos = 0;48 while ((pos = result.find('\"', pos)) >= 0) {49 result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1);50 pos += 4;51 }52 return result;53 }54 55 static UString valueToSourceString(ExecState* exec, JSValue* val)56 {57 if (val->isString()) {58 UString result("\"");59 result += escapeQuotes(val->toString(exec)) + "\"";60 return result;61 }62 63 return val->toString(exec);64 }65 66 static CString registerName(int r)67 {68 if (r == missingThisObjectMarker())69 return "<null>";70 71 return (UString("r") + UString::from(r)).UTF8String();72 }73 74 static CString constantName(ExecState* exec, int k, JSValue* value)75 {76 return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String();77 }78 79 static CString idName(int id0, const Identifier& ident)80 {81 return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String();82 }83 84 static UString regexpToSourceString(RegExp* regExp)85 {86 UString pattern = UString("/") + regExp->pattern() + "/";87 if (regExp->global())88 pattern += "g";89 if (regExp->ignoreCase())90 pattern += "i";91 if (regExp->multiline())92 pattern += "m";93 94 return pattern;95 }96 97 static CString regexpName(int re, RegExp* regexp)98 {99 return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String();100 }101 102 static UString pointerToSourceString(void* p)103 {104 char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0105 snprintf(buffer, sizeof(buffer), "%p", p);106 return buffer;107 }108 109 NEVER_INLINE static const char* debugHookName(int debugHookID)110 {111 switch (static_cast<DebugHookID>(debugHookID)) {112 case DidEnterCallFrame:113 return "didEnterCallFrame";114 case WillLeaveCallFrame:115 return "willLeaveCallFrame";116 case WillExecuteStatement:117 return "willExecuteStatement";118 case WillExecuteProgram:119 return "willExecuteProgram";120 case DidExecuteProgram:121 return "didExecuteProgram";122 case DidReachBreakpoint:123 return "didReachBreakpoint";124 }125 126 ASSERT_NOT_REACHED();127 return "";128 }129 130 static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset)131 {132 return it - begin + offset;133 }134 135 static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)136 {137 int r0 = (++it)->u.operand;138 int r1 = (++it)->u.operand;139 140 printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str());141 }142 143 static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)144 {145 int r0 = (++it)->u.operand;146 int r1 = (++it)->u.operand;147 int r2 = (++it)->u.operand;148 printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());149 }150 151 static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op)152 {153 int r0 = (++it)->u.operand;154 int offset = (++it)->u.operand;155 printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset));156 }157 158 static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)159 {160 int r0 = (++it)->u.operand;161 int r1 = (++it)->u.operand;162 int id0 = (++it)->u.operand;163 printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());164 it += 4;165 }166 167 static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)168 {169 int r0 = (++it)->u.operand;170 int id0 = (++it)->u.operand;171 int r1 = (++it)->u.operand;172 printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());173 it += 4;174 }175 176 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const177 {178 unsigned instructionOffset = vPC - m_instructions.begin();179 printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str());180 }181 182 void CodeBlock::printStructures(const Instruction* vPC) const183 {184 Interpreter* interpreter = m_globalData->interpreter;185 unsigned instructionOffset = vPC - m_instructions.begin();186 187 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {188 printStructure("get_by_id", vPC, 4);189 return;190 }191 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {192 printStructure("get_by_id_self", vPC, 4);193 return;194 }195 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {196 printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str());197 return;198 }199 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {200 printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_new", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str());201 return;202 }203 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {204 printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str());205 return;206 }207 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {208 printStructure("put_by_id", vPC, 4);209 return;210 }211 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {212 printStructure("put_by_id_replace", vPC, 4);213 return;214 }215 if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {216 printStructure("resolve_global", vPC, 4);217 return;218 }219 220 // These m_instructions doesn't ref Structures.221 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct));222 }223 224 void CodeBlock::dump(ExecState* exec) const225 {226 Vector<Instruction>::const_iterator begin = m_instructions.begin();227 Vector<Instruction>::const_iterator end = m_instructions.end();228 229 size_t instructionCount = 0;230 for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)231 if (exec->interpreter()->isOpcode(it->u.opcode))232 ++instructionCount;233 234 printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",235 static_cast<unsigned long>(instructionCount),236 static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),237 this, m_numParameters, m_numCalleeRegisters);238 239 for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)240 dump(exec, begin, it);241 242 if (!m_identifiers.isEmpty()) {243 printf("\nIdentifiers:\n");244 size_t i = 0;245 do {246 printf(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());247 ++i;248 } while (i != m_identifiers.size());249 }250 251 if (!m_constantRegisters.isEmpty()) {252 printf("\nConstants:\n");253 unsigned registerIndex = m_numVars;254 size_t i = 0;255 do {256 printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue(exec)).ascii());257 ++i;258 ++registerIndex;259 } while (i < m_constantRegisters.size());260 }261 262 if (!m_unexpectedConstants.isEmpty()) {263 printf("\nUnexpected Constants:\n");264 size_t i = 0;265 do {266 printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_unexpectedConstants[i]).ascii());267 ++i;268 } while (i < m_unexpectedConstants.size());269 }270 271 if (!m_regexps.isEmpty()) {272 printf("\nm_regexps:\n");273 size_t i = 0;274 do {275 printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_regexps[i].get()).ascii());276 ++i;277 } while (i < m_regexps.size());278 }279 280 if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())281 printf("\nStructures:\n");282 283 if (!m_globalResolveInstructions.isEmpty()) {284 size_t i = 0;285 do {286 printStructures(&m_instructions[m_globalResolveInstructions[i]]);287 ++i;288 } while (i < m_globalResolveInstructions.size());289 }290 if (!m_propertyAccessInstructions.isEmpty()) {291 size_t i = 0;292 do {293 printStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);294 ++i;295 } while (i < m_propertyAccessInstructions.size());296 }297 298 if (!m_exceptionHandlers.isEmpty()) {299 printf("\nException Handlers:\n");300 unsigned i = 0;301 do {302 printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_exceptionHandlers[i].start, m_exceptionHandlers[i].end, m_exceptionHandlers[i].target);303 ++i;304 } while (i < m_exceptionHandlers.size());305 }306 307 if (!m_immediateSwitchJumpTables.isEmpty()) {308 printf("Immediate Switch Jump Tables:\n");309 unsigned i = 0;310 do {311 printf(" %1d = {\n", i);312 int entry = 0;313 Vector<int32_t>::const_iterator end = m_immediateSwitchJumpTables[i].branchOffsets.end();314 for (Vector<int32_t>::const_iterator iter = m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {315 if (!*iter)316 continue;317 printf("\t\t%4d => %04d\n", entry + m_immediateSwitchJumpTables[i].min, *iter);318 }319 printf(" }\n");320 ++i;321 } while (i < m_immediateSwitchJumpTables.size());322 }323 324 if (!m_characterSwitchJumpTables.isEmpty()) {325 printf("\nCharacter Switch Jump Tables:\n");326 unsigned i = 0;327 do {328 printf(" %1d = {\n", i);329 int entry = 0;330 Vector<int32_t>::const_iterator end = m_characterSwitchJumpTables[i].branchOffsets.end();331 for (Vector<int32_t>::const_iterator iter = m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {332 if (!*iter)333 continue;334 ASSERT(!((i + m_characterSwitchJumpTables[i].min) & ~0xFFFF));335 UChar ch = static_cast<UChar>(entry + m_characterSwitchJumpTables[i].min);336 printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);337 }338 printf(" }\n");339 ++i;340 } while (i < m_characterSwitchJumpTables.size());341 }342 343 if (!m_stringSwitchJumpTables.isEmpty()) {344 printf("\nString Switch Jump Tables:\n");345 unsigned i = 0;346 do {347 printf(" %1d = {\n", i);348 StringJumpTable::StringOffsetTable::const_iterator end = m_stringSwitchJumpTables[i].offsetTable.end();349 for (StringJumpTable::StringOffsetTable::const_iterator iter = m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)350 printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);351 printf(" }\n");352 ++i;353 } while (i < m_stringSwitchJumpTables.size());354 }355 356 printf("\n");357 }358 359 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const360 {361 int location = it - begin;362 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {363 case op_enter: {364 printf("[%4d] enter\n", location);365 break;366 }367 case op_enter_with_activation: {368 int r0 = (++it)->u.operand;369 printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str());370 break;371 }372 case op_create_arguments: {373 printf("[%4d] create_arguments\n", location);374 break;375 }376 case op_convert_this: {377 int r0 = (++it)->u.operand;378 printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());379 break;380 }381 case op_unexpected_load: {382 int r0 = (++it)->u.operand;383 int k0 = (++it)->u.operand;384 printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, m_unexpectedConstants[k0]).c_str());385 break;386 }387 case op_new_object: {388 int r0 = (++it)->u.operand;389 printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str());390 break;391 }392 case op_new_array: {393 int dst = (++it)->u.operand;394 int argv = (++it)->u.operand;395 int argc = (++it)->u.operand;396 printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc);397 break;398 }399 case op_new_regexp: {400 int r0 = (++it)->u.operand;401 int re0 = (++it)->u.operand;402 printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, m_regexps[re0].get()).c_str());403 break;404 }405 case op_mov: {406 int r0 = (++it)->u.operand;407 int r1 = (++it)->u.operand;408 printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());409 break;410 }411 case op_not: {412 printUnaryOp(location, it, "not");413 break;414 }415 case op_eq: {416 printBinaryOp(location, it, "eq");417 break;418 }419 case op_eq_null: {420 printUnaryOp(location, it, "eq_null");421 break;422 }423 case op_neq: {424 printBinaryOp(location, it, "neq");425 break;426 }427 case op_neq_null: {428 printUnaryOp(location, it, "neq_null");429 break;430 }431 case op_stricteq: {432 printBinaryOp(location, it, "stricteq");433 break;434 }435 case op_nstricteq: {436 printBinaryOp(location, it, "nstricteq");437 break;438 }439 case op_less: {440 printBinaryOp(location, it, "less");441 break;442 }443 case op_lesseq: {444 printBinaryOp(location, it, "lesseq");445 break;446 }447 case op_pre_inc: {448 int r0 = (++it)->u.operand;449 printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str());450 break;451 }452 case op_pre_dec: {453 int r0 = (++it)->u.operand;454 printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str());455 break;456 }457 case op_post_inc: {458 printUnaryOp(location, it, "post_inc");459 break;460 }461 case op_post_dec: {462 printUnaryOp(location, it, "post_dec");463 break;464 }465 case op_to_jsnumber: {466 printUnaryOp(location, it, "to_jsnumber");467 break;468 }469 case op_negate: {470 printUnaryOp(location, it, "negate");471 break;472 }473 case op_add: {474 printBinaryOp(location, it, "add");475 ++it;476 break;477 }478 case op_mul: {479 printBinaryOp(location, it, "mul");480 ++it;481 break;482 }483 case op_div: {484 printBinaryOp(location, it, "div");485 break;486 }487 case op_mod: {488 printBinaryOp(location, it, "mod");489 break;490 }491 case op_sub: {492 printBinaryOp(location, it, "sub");493 ++it;494 break;495 }496 case op_lshift: {497 printBinaryOp(location, it, "lshift");498 break;499 }500 case op_rshift: {501 printBinaryOp(location, it, "rshift");502 break;503 }504 case op_urshift: {505 printBinaryOp(location, it, "urshift");506 break;507 }508 case op_bitand: {509 printBinaryOp(location, it, "bitand");510 ++it;511 break;512 }513 case op_bitxor: {514 printBinaryOp(location, it, "bitxor");515 ++it;516 break;517 }518 case op_bitor: {519 printBinaryOp(location, it, "bitor");520 ++it;521 break;522 }523 case op_bitnot: {524 printUnaryOp(location, it, "bitnot");525 break;526 }527 case op_instanceof: {528 int r0 = (++it)->u.operand;529 int r1 = (++it)->u.operand;530 int r2 = (++it)->u.operand;531 int r3 = (++it)->u.operand;532 printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str());533 break;534 }535 case op_typeof: {536 printUnaryOp(location, it, "typeof");537 break;538 }539 case op_is_undefined: {540 printUnaryOp(location, it, "is_undefined");541 break;542 }543 case op_is_boolean: {544 printUnaryOp(location, it, "is_boolean");545 break;546 }547 case op_is_number: {548 printUnaryOp(location, it, "is_number");549 break;550 }551 case op_is_string: {552 printUnaryOp(location, it, "is_string");553 break;554 }555 case op_is_object: {556 printUnaryOp(location, it, "is_object");557 break;558 }559 case op_is_function: {560 printUnaryOp(location, it, "is_function");561 break;562 }563 case op_in: {564 printBinaryOp(location, it, "in");565 break;566 }567 case op_resolve: {568 int r0 = (++it)->u.operand;569 int id0 = (++it)->u.operand;570 printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());571 break;572 }573 case op_resolve_skip: {574 int r0 = (++it)->u.operand;575 int id0 = (++it)->u.operand;576 int skipLevels = (++it)->u.operand;577 printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);578 break;579 }580 case op_resolve_global: {581 int r0 = (++it)->u.operand;582 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);583 int id0 = (++it)->u.operand;584 printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str());585 it += 2;586 break;587 }588 case op_get_scoped_var: {589 int r0 = (++it)->u.operand;590 int index = (++it)->u.operand;591 int skipLevels = (++it)->u.operand;592 printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels);593 break;594 }595 case op_put_scoped_var: {596 int index = (++it)->u.operand;597 int skipLevels = (++it)->u.operand;598 int r0 = (++it)->u.operand;599 printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str());600 break;601 }602 case op_get_global_var: {603 int r0 = (++it)->u.operand;604 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);605 int index = (++it)->u.operand;606 printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);607 break;608 }609 case op_put_global_var: {610 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);611 int index = (++it)->u.operand;612 int r0 = (++it)->u.operand;613 printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());614 break;615 }616 case op_resolve_base: {617 int r0 = (++it)->u.operand;618 int id0 = (++it)->u.operand;619 printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());620 break;621 }622 case op_resolve_with_base: {623 int r0 = (++it)->u.operand;624 int r1 = (++it)->u.operand;625 int id0 = (++it)->u.operand;626 printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());627 break;628 }629 case op_resolve_func: {630 int r0 = (++it)->u.operand;631 int r1 = (++it)->u.operand;632 int id0 = (++it)->u.operand;633 printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());634 break;635 }636 case op_get_by_id: {637 printGetByIdOp(location, it, m_identifiers, "get_by_id");638 break;639 }640 case op_get_by_id_self: {641 printGetByIdOp(location, it, m_identifiers, "get_by_id_self");642 break;643 }644 case op_get_by_id_self_list: {645 printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list");646 break;647 }648 case op_get_by_id_proto: {649 printGetByIdOp(location, it, m_identifiers, "get_by_id_proto");650 break;651 }652 case op_get_by_id_proto_list: {653 printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list");654 break;655 }656 case op_get_by_id_chain: {657 printGetByIdOp(location, it, m_identifiers, "get_by_id_chain");658 break;659 }660 case op_get_by_id_generic: {661 printGetByIdOp(location, it, m_identifiers, "get_by_id_generic");662 break;663 }664 case op_get_array_length: {665 printGetByIdOp(location, it, m_identifiers, "get_array_length");666 break;667 }668 case op_get_string_length: {669 printGetByIdOp(location, it, m_identifiers, "get_string_length");670 break;671 }672 case op_put_by_id: {673 printPutByIdOp(location, it, m_identifiers, "put_by_id");674 break;675 }676 case op_put_by_id_replace: {677 printPutByIdOp(location, it, m_identifiers, "put_by_id_replace");678 break;679 }680 case op_put_by_id_transition: {681 printPutByIdOp(location, it, m_identifiers, "put_by_id_transition");682 break;683 }684 case op_put_by_id_generic: {685 printPutByIdOp(location, it, m_identifiers, "put_by_id_generic");686 break;687 }688 case op_put_getter: {689 int r0 = (++it)->u.operand;690 int id0 = (++it)->u.operand;691 int r1 = (++it)->u.operand;692 printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());693 break;694 }695 case op_put_setter: {696 int r0 = (++it)->u.operand;697 int id0 = (++it)->u.operand;698 int r1 = (++it)->u.operand;699 printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());700 break;701 }702 case op_del_by_id: {703 int r0 = (++it)->u.operand;704 int r1 = (++it)->u.operand;705 int id0 = (++it)->u.operand;706 printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());707 break;708 }709 case op_get_by_val: {710 int r0 = (++it)->u.operand;711 int r1 = (++it)->u.operand;712 int r2 = (++it)->u.operand;713 printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());714 break;715 }716 case op_put_by_val: {717 int r0 = (++it)->u.operand;718 int r1 = (++it)->u.operand;719 int r2 = (++it)->u.operand;720 printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());721 break;722 }723 case op_del_by_val: {724 int r0 = (++it)->u.operand;725 int r1 = (++it)->u.operand;726 int r2 = (++it)->u.operand;727 printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());728 break;729 }730 case op_put_by_index: {731 int r0 = (++it)->u.operand;732 unsigned n0 = (++it)->u.operand;733 int r1 = (++it)->u.operand;734 printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str());735 break;736 }737 case op_jmp: {738 int offset = (++it)->u.operand;739 printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));740 break;741 }742 case op_loop: {743 int offset = (++it)->u.operand;744 printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));745 break;746 }747 case op_jtrue: {748 printConditionalJump(begin, it, location, "jtrue");749 break;750 }751 case op_loop_if_true: {752 printConditionalJump(begin, it, location, "loop_if_true");753 break;754 }755 case op_jfalse: {756 printConditionalJump(begin, it, location, "jfalse");757 break;758 }759 case op_jeq_null: {760 printConditionalJump(begin, it, location, "jeq_null");761 break;762 }763 case op_jneq_null: {764 printConditionalJump(begin, it, location, "jneq_null");765 break;766 }767 case op_jnless: {768 int r0 = (++it)->u.operand;769 int r1 = (++it)->u.operand;770 int offset = (++it)->u.operand;771 printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));772 break;773 }774 case op_loop_if_less: {775 int r0 = (++it)->u.operand;776 int r1 = (++it)->u.operand;777 int offset = (++it)->u.operand;778 printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));779 break;780 }781 case op_loop_if_lesseq: {782 int r0 = (++it)->u.operand;783 int r1 = (++it)->u.operand;784 int offset = (++it)->u.operand;785 printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));786 break;787 }788 case op_switch_imm: {789 int tableIndex = (++it)->u.operand;790 int defaultTarget = (++it)->u.operand;791 int scrutineeRegister = (++it)->u.operand;792 printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());793 break;794 }795 case op_switch_char: {796 int tableIndex = (++it)->u.operand;797 int defaultTarget = (++it)->u.operand;798 int scrutineeRegister = (++it)->u.operand;799 printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());800 break;801 }802 case op_switch_string: {803 int tableIndex = (++it)->u.operand;804 int defaultTarget = (++it)->u.operand;805 int scrutineeRegister = (++it)->u.operand;806 printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());807 break;808 }809 case op_new_func: {810 int r0 = (++it)->u.operand;811 int f0 = (++it)->u.operand;812 printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0);813 break;814 }815 case op_new_func_exp: {816 int r0 = (++it)->u.operand;817 int f0 = (++it)->u.operand;818 printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0);819 break;820 }821 case op_call: {822 int dst = (++it)->u.operand;823 int func = (++it)->u.operand;824 int argCount = (++it)->u.operand;825 int registerOffset = (++it)->u.operand;826 printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);827 break;828 }829 case op_call_eval: {830 int dst = (++it)->u.operand;831 int func = (++it)->u.operand;832 int argCount = (++it)->u.operand;833 int registerOffset = (++it)->u.operand;834 printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);835 break;836 }837 case op_tear_off_activation: {838 int r0 = (++it)->u.operand;839 printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());840 break;841 }842 case op_tear_off_arguments: {843 printf("[%4d] tear_off_arguments\n", location);844 break;845 }846 case op_ret: {847 int r0 = (++it)->u.operand;848 printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str());849 break;850 }851 case op_construct: {852 int dst = (++it)->u.operand;853 int func = (++it)->u.operand;854 int argCount = (++it)->u.operand;855 int registerOffset = (++it)->u.operand;856 int proto = (++it)->u.operand;857 int thisRegister = (++it)->u.operand;858 printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str());859 break;860 }861 case op_construct_verify: {862 int r0 = (++it)->u.operand;863 int r1 = (++it)->u.operand;864 printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());865 break;866 }867 case op_get_pnames: {868 int r0 = (++it)->u.operand;869 int r1 = (++it)->u.operand;870 printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());871 break;872 }873 case op_next_pname: {874 int dest = (++it)->u.operand;875 int iter = (++it)->u.operand;876 int offset = (++it)->u.operand;877 printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset));878 break;879 }880 case op_push_scope: {881 int r0 = (++it)->u.operand;882 printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str());883 break;884 }885 case op_pop_scope: {886 printf("[%4d] pop_scope\n", location);887 break;888 }889 case op_push_new_scope: {890 int r0 = (++it)->u.operand;891 int id0 = (++it)->u.operand;892 int r1 = (++it)->u.operand;893 printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());894 break;895 }896 case op_jmp_scopes: {897 int scopeDelta = (++it)->u.operand;898 int offset = (++it)->u.operand;899 printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset));900 break;901 }902 case op_catch: {903 int r0 = (++it)->u.operand;904 printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str());905 break;906 }907 case op_throw: {908 int r0 = (++it)->u.operand;909 printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str());910 break;911 }912 case op_new_error: {913 int r0 = (++it)->u.operand;914 int errorType = (++it)->u.operand;915 int k0 = (++it)->u.operand;916 printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, m_unexpectedConstants[k0]).c_str());917 break;918 }919 case op_jsr: {920 int retAddrDst = (++it)->u.operand;921 int offset = (++it)->u.operand;922 printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset));923 break;924 }925 case op_sret: {926 int retAddrSrc = (++it)->u.operand;927 printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str());928 break;929 }930 case op_debug: {931 int debugHookID = (++it)->u.operand;932 int firstLine = (++it)->u.operand;933 int lastLine = (++it)->u.operand;934 printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);935 break;936 }937 case op_profile_will_call: {938 int function = (++it)->u.operand;939 printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str());940 break;941 }942 case op_profile_did_call: {943 int function = (++it)->u.operand;944 printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str());945 break;946 }947 case op_end: {948 int r0 = (++it)->u.operand;949 printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str());950 break;951 }952 }953 }954 955 #endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)956 957 CodeBlock::~CodeBlock()958 {959 for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)960 derefStructures(&m_instructions[m_globalResolveInstructions[i]]);961 962 for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {963 derefStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);964 if (m_propertyAccessInstructions[i].stubRoutine)965 WTF::fastFreeExecutable(m_propertyAccessInstructions[i].stubRoutine);966 }967 968 for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {969 CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];970 if (callLinkInfo->isLinked())971 callLinkInfo->callee->removeCaller(callLinkInfo);972 }973 974 #if ENABLE(JIT)975 unlinkCallers();976 977 if (m_jitCode)978 WTF::fastFreeExecutable(m_jitCode);979 #endif980 }981 982 #if ENABLE(JIT)983 void CodeBlock::unlinkCallers()984 {985 size_t size = m_linkedCallerList.size();986 for (size_t i = 0; i < size; ++i) {987 CallLinkInfo* currentCaller = m_linkedCallerList[i];988 JIT::unlinkCall(currentCaller);989 currentCaller->setUnlinked();990 }991 m_linkedCallerList.clear();992 }993 #endif994 995 void CodeBlock::derefStructures(Instruction* vPC) const996 {997 Interpreter* interpreter = m_globalData->interpreter;998 999 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {1000 vPC[4].u.structure->deref();1001 return;1002 }1003 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {1004 vPC[4].u.structure->deref();1005 vPC[5].u.structure->deref();1006 return;1007 }1008 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {1009 vPC[4].u.structure->deref();1010 vPC[5].u.structureChain->deref();1011 return;1012 }1013 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {1014 vPC[4].u.structure->deref();1015 vPC[5].u.structure->deref();1016 vPC[6].u.structureChain->deref();1017 return;1018 }1019 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {1020 vPC[4].u.structure->deref();1021 return;1022 }1023 if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {1024 if(vPC[4].u.structure)1025 vPC[4].u.structure->deref();1026 return;1027 }1028 if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))1029 || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {1030 PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;1031 polymorphicStructures->derefStructures(vPC[5].u.operand);1032 delete polymorphicStructures;1033 return;1034 }1035 1036 // These instructions don't ref their Structures.1037 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));1038 }1039 1040 void CodeBlock::refStructures(Instruction* vPC) const1041 {1042 Interpreter* interpreter = m_globalData->interpreter;1043 1044 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {1045 vPC[4].u.structure->ref();1046 return;1047 }1048 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {1049 vPC[4].u.structure->ref();1050 vPC[5].u.structure->ref();1051 return;1052 }1053 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {1054 vPC[4].u.structure->ref();1055 vPC[5].u.structureChain->ref();1056 return;1057 }1058 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {1059 vPC[4].u.structure->ref();1060 vPC[5].u.structure->ref();1061 vPC[6].u.structureChain->ref();1062 return;1063 }1064 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {1065 vPC[4].u.structure->ref();1066 return;1067 }1068 1069 // These instructions don't ref their Structures.1070 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));1071 }1072 1073 void CodeBlock::mark()1074 {1075 for (size_t i = 0; i < m_constantRegisters.size(); ++i)1076 if (!m_constantRegisters[i].marked())1077 m_constantRegisters[i].mark();1078 1079 for (size_t i = 0; i < m_unexpectedConstants.size(); ++i)1080 if (!m_unexpectedConstants[i]->marked())1081 m_unexpectedConstants[i]->mark();1082 1083 for (size_t i = 0; i < m_functions.size(); ++i)1084 m_functions[i]->body()->mark();1085 1086 for (size_t i = 0; i < m_functionExpressions.size(); ++i)1087 m_functionExpressions[i]->body()->mark();1088 }1089 1090 bool CodeBlock::getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth)1091 {1092 Vector<HandlerInfo>::iterator ptr = m_exceptionHandlers.begin();1093 Vector<HandlerInfo>::iterator end = m_exceptionHandlers.end();1094 unsigned addressOffset = vPC - m_instructions.begin();1095 ASSERT(addressOffset < m_instructions.size());1096 1097 for (; ptr != end; ++ptr) {1098 // Handlers are ordered innermost first, so the first handler we encounter1099 // that contains the source address is the correct handler to use.1100 if (ptr->start <= addressOffset && ptr->end >= addressOffset) {1101 scopeDepth = ptr->scopeDepth;1102 target = m_instructions.begin() + ptr->target;1103 return true;1104 }1105 }1106 return false;1107 }1108 1109 void* CodeBlock::nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC)1110 {1111 Vector<HandlerInfo>::iterator ptr = m_exceptionHandlers.begin();1112 Vector<HandlerInfo>::iterator end = m_exceptionHandlers.end();1113 1114 for (; ptr != end; ++ptr) {1115 Instruction*target = m_instructions.begin() + ptr->target;1116 if (handlerVPC == target)1117 return ptr->nativeCode;1118 }1119 1120 return 0;1121 }1122 1123 int CodeBlock::lineNumberForVPC(const Instruction* vPC)1124 {1125 unsigned instructionOffset = vPC - m_instructions.begin();1126 ASSERT(instructionOffset < m_instructions.size());1127 1128 if (!m_lineInfo.size())1129 return m_ownerNode->source().firstLine(); // Empty function1130 1131 int low = 0;1132 int high = m_lineInfo.size();1133 while (low < high) {1134 int mid = low + (high - low) / 2;1135 if (m_lineInfo[mid].instructionOffset <= instructionOffset)1136 low = mid + 1;1137 else1138 high = mid;1139 }1140 1141 if (!low)1142 return m_ownerNode->source().firstLine();1143 return m_lineInfo[low - 1].lineNumber;1144 }1145 1146 int CodeBlock::expressionRangeForVPC(const Instruction* vPC, int& divot, int& startOffset, int& endOffset)1147 {1148 unsigned instructionOffset = vPC - m_instructions.begin();1149 ASSERT(instructionOffset < m_instructions.size());1150 1151 if (!m_expressionInfo.size()) {1152 // We didn't think anything could throw. Apparently we were wrong.1153 startOffset = 0;1154 endOffset = 0;1155 divot = 0;1156 return lineNumberForVPC(vPC);1157 }1158 1159 int low = 0;1160 int high = m_expressionInfo.size();1161 while (low < high) {1162 int mid = low + (high - low) / 2;1163 if (m_expressionInfo[mid].instructionOffset <= instructionOffset)1164 low = mid + 1;1165 else1166 high = mid;1167 }1168 1169 ASSERT(low);1170 if (!low) {1171 startOffset = 0;1172 endOffset = 0;1173 divot = 0;1174 return lineNumberForVPC(vPC);1175 }1176 1177 startOffset = m_expressionInfo[low - 1].startOffset;1178 endOffset = m_expressionInfo[low - 1].endOffset;1179 divot = m_expressionInfo[low - 1].divotPoint + m_sourceOffset;1180 return lineNumberForVPC(vPC);1181 }1182 1183 void CodeBlock::shrinkToFit()1184 {1185 m_instructions.shrinkToFit();1186 1187 m_globalResolveInstructions.shrinkToFit();1188 m_propertyAccessInstructions.shrinkToFit();1189 m_callLinkInfos.shrinkToFit();1190 m_linkedCallerList.shrinkToFit();1191 1192 m_exceptionHandlers.shrinkToFit();1193 m_expressionInfo.shrinkToFit();1194 m_lineInfo.shrinkToFit();1195 1196 m_identifiers.shrinkToFit();1197 m_functions.shrinkToFit();1198 m_functionExpressions.shrinkToFit();1199 m_constantRegisters.shrinkToFit();1200 m_unexpectedConstants.shrinkToFit();1201 m_regexps.shrinkToFit();1202 1203 m_immediateSwitchJumpTables.shrinkToFit();1204 m_characterSwitchJumpTables.shrinkToFit();1205 m_stringSwitchJumpTables.shrinkToFit();1206 }1207 34 1208 35 int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset) -
trunk/JavaScriptCore/bytecode/JumpTable.h
r39070 r39071 28 28 */ 29 29 30 #ifndef CodeBlock_h31 #define CodeBlock_h30 #ifndef JumpTable_h 31 #define JumpTable_h 32 32 33 #include "EvalCodeCache.h"34 #include "Instruction.h"35 #include "JSGlobalObject.h"36 #include "Nodes.h"37 #include "RegExp.h"38 33 #include "UString.h" 39 #include <wtf/ RefPtr.h>34 #include <wtf/HashMap.h> 40 35 #include <wtf/Vector.h> 41 36 42 37 namespace JSC { 43 44 class ExecState;45 46 enum CodeType { GlobalCode, EvalCode, FunctionCode };47 48 static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }49 50 struct HandlerInfo {51 uint32_t start;52 uint32_t end;53 uint32_t target;54 uint32_t scopeDepth;55 void* nativeCode;56 };57 58 struct ExpressionRangeInfo {59 enum {60 MaxOffset = (1 << 7) - 1,61 MaxDivot = (1 << 25) - 162 };63 uint32_t instructionOffset : 25;64 uint32_t divotPoint : 25;65 uint32_t startOffset : 7;66 uint32_t endOffset : 7;67 };68 69 struct LineInfo {70 uint32_t instructionOffset;71 int32_t lineNumber;72 };73 38 74 39 struct OffsetLocation { … … 78 43 #endif 79 44 }; 80 81 struct StructureStubInfo {82 StructureStubInfo(unsigned bytecodeIndex)83 : bytecodeIndex(bytecodeIndex)84 , stubRoutine(0)85 , callReturnLocation(0)86 , hotPathBegin(0)87 {88 }89 90 unsigned bytecodeIndex;91 void* stubRoutine;92 void* callReturnLocation;93 void* hotPathBegin;94 };95 96 struct CallLinkInfo {97 CallLinkInfo()98 : callReturnLocation(0)99 , hotPathBegin(0)100 , hotPathOther(0)101 , coldPathOther(0)102 , callee(0)103 {104 }105 106 unsigned bytecodeIndex;107 void* callReturnLocation;108 void* hotPathBegin;109 void* hotPathOther;110 void* coldPathOther;111 CodeBlock* callee;112 unsigned position;113 114 void setUnlinked() { callee = 0; }115 bool isLinked() { return callee; }116 };117 118 inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)119 {120 return structureStubInfo->callReturnLocation;121 }122 123 inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)124 {125 return callLinkInfo->callReturnLocation;126 }127 128 // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,129 // compares result with key (KeyTypes should be comparable with '--', '<', '>').130 // Optimized for cases where the array contains the key, checked by assertions.131 template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>132 inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)133 {134 // The array must contain at least one element (pre-condition, array does conatin key).135 // If the array only contains one element, no need to do the comparison.136 while (size > 1) {137 // Pick an element to check, half way through the array, and read the value.138 int pos = (size - 1) >> 1;139 KeyType val = valueAtPosition(&array[pos]);140 141 // If the key matches, success!142 if (val == key)143 return &array[pos];144 // The item we are looking for is smaller than the item being check; reduce the value of 'size',145 // chopping off the right hand half of the array.146 else if (key < val)147 size = pos;148 // Discard all values in the left hand half of the array, up to and including the item at pos.149 else {150 size -= (pos + 1);151 array += (pos + 1);152 }153 154 // 'size' should never reach zero.155 ASSERT(size);156 }157 158 // If we reach this point we've chopped down to one element, no need to check it matches159 ASSERT(size == 1);160 ASSERT(key == valueAtPosition(&array[0]));161 return &array[0];162 }163 45 164 46 struct StringJumpTable { … … 216 98 }; 217 99 218 class CodeBlock {219 friend class JIT;220 public:221 CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)222 : m_numCalleeRegisters(0)223 , m_numConstants(0)224 , m_numVars(0)225 , m_numParameters(0)226 , m_ownerNode(ownerNode)227 , m_globalData(0)228 #if ENABLE(JIT)229 , m_jitCode(0)230 #endif231 , m_needsFullScopeChain(ownerNode->needsActivation())232 , m_usesEval(ownerNode->usesEval())233 , m_codeType(codeType)234 , m_source(sourceProvider)235 , m_sourceOffset(sourceOffset)236 {237 ASSERT(m_source);238 }239 240 ~CodeBlock();241 242 #if ENABLE(JIT)243 void unlinkCallers();244 #endif245 246 void addCaller(CallLinkInfo* caller)247 {248 caller->callee = this;249 caller->position = m_linkedCallerList.size();250 m_linkedCallerList.append(caller);251 }252 253 void removeCaller(CallLinkInfo* caller)254 {255 unsigned pos = caller->position;256 unsigned lastPos = m_linkedCallerList.size() - 1;257 258 if (pos != lastPos) {259 m_linkedCallerList[pos] = m_linkedCallerList[lastPos];260 m_linkedCallerList[pos]->position = pos;261 }262 m_linkedCallerList.shrink(lastPos);263 }264 265 inline bool isKnownNotImmediate(int index)266 {267 if (index == m_thisRegister)268 return true;269 270 if (isConstantRegisterIndex(index))271 return !JSImmediate::isImmediate(getConstant(index));272 273 return false;274 }275 276 ALWAYS_INLINE bool isConstantRegisterIndex(int index)277 {278 return index >= m_numVars && index < m_numVars + m_numConstants;279 }280 281 ALWAYS_INLINE JSValue* getConstant(int index)282 {283 return m_constantRegisters[index - m_numVars].getJSValue();284 }285 286 ALWAYS_INLINE bool isTemporaryRegisterIndex(int index)287 {288 return index >= m_numVars + m_numConstants;289 }290 291 #if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING292 void dump(ExecState*) const;293 void printStructures(const Instruction*) const;294 void printStructure(const char* name, const Instruction*, int operand) const;295 #endif296 int expressionRangeForVPC(const Instruction*, int& divot, int& startOffset, int& endOffset);297 int lineNumberForVPC(const Instruction* vPC);298 bool getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth);299 void* nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC);300 301 void mark();302 void refStructures(Instruction* vPC) const;303 void derefStructures(Instruction* vPC) const;304 305 StructureStubInfo& getStubInfo(void* returnAddress)306 {307 return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_propertyAccessInstructions.begin(), m_propertyAccessInstructions.size(), returnAddress));308 }309 310 CallLinkInfo& getCallLinkInfo(void* returnAddress)311 {312 return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress));313 }314 315 316 Vector<Instruction>& instructions() { return m_instructions; }317 #if ENABLE(JIT)318 void setJITCode(void* jitCode) { m_jitCode = jitCode; }319 void* jitCode() { return m_jitCode; }320 #endif321 322 ScopeNode* ownerNode() const { return m_ownerNode; }323 324 void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }325 326 void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }327 int thisRegister() const { return m_thisRegister; }328 329 void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }330 bool needsFullScopeChain() const { return m_needsFullScopeChain; }331 void setUsesEval(bool usesEval) { m_usesEval = usesEval; }332 bool usesEval() const { return m_usesEval; }333 void setUsesArguments(bool usesArguments) { m_usesArguments = usesArguments; }334 bool usesArguments() const { return m_usesArguments; }335 336 CodeType codeType() const { return m_codeType; }337 338 SourceProvider* source() const { return m_source.get(); }339 unsigned sourceOffset() const { return m_sourceOffset; }340 341 void addGlobalResolveInstruction(unsigned globalResolveInstructions) { m_globalResolveInstructions.append(globalResolveInstructions); }342 343 size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }344 void addPropertyAccessInstruction(unsigned propertyAccessInstructions) { m_propertyAccessInstructions.append(StructureStubInfo(propertyAccessInstructions)); }345 StructureStubInfo& propertyAccessInstruction(int index) { return m_propertyAccessInstructions[index]; }346 347 size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }348 void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }349 CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }350 351 size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }352 void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }353 unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }354 unsigned lastJumpTarget() const { return m_jumpTargets.last(); }355 356 size_t numberOfExceptionHandlers() const { return m_exceptionHandlers.size(); }357 void addExceptionHandler(const HandlerInfo& hanler) { return m_exceptionHandlers.append(hanler); }358 HandlerInfo& exceptionHandler(int index) { return m_exceptionHandlers[index]; }359 360 void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { return m_expressionInfo.append(expressionInfo); }361 362 size_t numberOfLineInfos() const { return m_lineInfo.size(); }363 void addLineInfo(const LineInfo& lineInfo) { return m_lineInfo.append(lineInfo); }364 LineInfo& lastLineInfo() { return m_lineInfo.last(); }365 366 #if ENABLE(JIT)367 HashMap<void*, unsigned>& jitReturnAddressVPCMap() { return m_jitReturnAddressVPCMap; }368 #endif369 370 // Constant Pool371 372 size_t numberOfIdentifiers() const { return m_identifiers.size(); }373 void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }374 Identifier& identifier(int index) { return m_identifiers[index]; }375 376 size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }377 void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }378 Register& constantRegister(int index) { return m_constantRegisters[index]; }379 380 unsigned addFunction(FuncDeclNode* n) { unsigned size = m_functions.size(); m_functions.append(n); return size; }381 FuncDeclNode* function(int index) const { return m_functions[index].get(); }382 383 unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; }384 FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); }385 386 unsigned addUnexpectedConstant(JSValue* v) { unsigned size = m_unexpectedConstants.size(); m_unexpectedConstants.append(v); return size; }387 JSValue* unexpectedConstant(int index) const { return m_unexpectedConstants[index]; }388 389 unsigned addRegExp(RegExp* r) { unsigned size = m_regexps.size(); m_regexps.append(r); return size; }390 RegExp* regexp(int index) const { return m_regexps[index].get(); }391 392 // Jump Tables393 394 size_t numberOfImmediateSwitchJumpTables() const { return m_immediateSwitchJumpTables.size(); }395 SimpleJumpTable& addImmediateSwitchJumpTable() { m_immediateSwitchJumpTables.append(SimpleJumpTable()); return m_immediateSwitchJumpTables.last(); }396 SimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { return m_immediateSwitchJumpTables[tableIndex]; }397 398 size_t numberOfCharacterSwitchJumpTables() const { return m_characterSwitchJumpTables.size(); }399 SimpleJumpTable& addCharacterSwitchJumpTable() { m_characterSwitchJumpTables.append(SimpleJumpTable()); return m_characterSwitchJumpTables.last(); }400 SimpleJumpTable& characterSwitchJumpTable(int tableIndex) { return m_characterSwitchJumpTables[tableIndex]; }401 402 size_t numberOfStringSwitchJumpTables() const { return m_stringSwitchJumpTables.size(); }403 StringJumpTable& addStringSwitchJumpTable() { m_stringSwitchJumpTables.append(StringJumpTable()); return m_stringSwitchJumpTables.last(); }404 StringJumpTable& stringSwitchJumpTable(int tableIndex) { return m_stringSwitchJumpTables[tableIndex]; }405 406 407 SymbolTable& symbolTable() { return m_symbolTable; }408 EvalCodeCache& evalCodeCache() { return m_evalCodeCache; }409 410 void shrinkToFit();411 412 // FIXME: Make these remaining members private.413 414 int m_numCalleeRegisters;415 // NOTE: numConstants holds the number of constant registers allocated416 // by the code generator, not the number of constant registers used.417 // (Duplicate constants are uniqued during code generation, and spare418 // constant registers may be allocated.)419 int m_numConstants;420 int m_numVars;421 int m_numParameters;422 423 private:424 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)425 void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;426 #endif427 428 ScopeNode* m_ownerNode;429 JSGlobalData* m_globalData;430 431 Vector<Instruction> m_instructions;432 #if ENABLE(JIT)433 void* m_jitCode;434 #endif435 436 int m_thisRegister;437 438 bool m_needsFullScopeChain;439 bool m_usesEval;440 bool m_usesArguments;441 442 CodeType m_codeType;443 444 RefPtr<SourceProvider> m_source;445 unsigned m_sourceOffset;446 447 Vector<unsigned> m_globalResolveInstructions;448 Vector<StructureStubInfo> m_propertyAccessInstructions;449 Vector<CallLinkInfo> m_callLinkInfos;450 Vector<CallLinkInfo*> m_linkedCallerList;451 452 Vector<unsigned> m_jumpTargets;453 454 Vector<HandlerInfo> m_exceptionHandlers;455 Vector<ExpressionRangeInfo> m_expressionInfo;456 Vector<LineInfo> m_lineInfo;457 458 #if ENABLE(JIT)459 HashMap<void*, unsigned> m_jitReturnAddressVPCMap;460 #endif461 462 // Constant Pool463 Vector<Identifier> m_identifiers;464 Vector<Register> m_constantRegisters;465 Vector<RefPtr<FuncDeclNode> > m_functions;466 Vector<RefPtr<FuncExprNode> > m_functionExpressions;467 Vector<JSValue*> m_unexpectedConstants;468 Vector<RefPtr<RegExp> > m_regexps;469 470 // Jump Tables471 Vector<SimpleJumpTable> m_immediateSwitchJumpTables;472 Vector<SimpleJumpTable> m_characterSwitchJumpTables;473 Vector<StringJumpTable> m_stringSwitchJumpTables;474 475 SymbolTable m_symbolTable;476 477 EvalCodeCache m_evalCodeCache;478 };479 480 // Program code is not marked by any function, so we make the global object481 // responsible for marking it.482 483 class ProgramCodeBlock : public CodeBlock {484 public:485 ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)486 : CodeBlock(ownerNode, codeType, sourceProvider, 0)487 , m_globalObject(globalObject)488 {489 m_globalObject->codeBlocks().add(this);490 }491 492 ~ProgramCodeBlock()493 {494 if (m_globalObject)495 m_globalObject->codeBlocks().remove(this);496 }497 498 void clearGlobalObject() { m_globalObject = 0; }499 500 private:501 JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.502 };503 504 class EvalCodeBlock : public ProgramCodeBlock {505 public:506 EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)507 : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)508 {509 }510 };511 512 100 } // namespace JSC 513 101 514 #endif // CodeBlock_h102 #endif // JumpTable_h
Note:
See TracChangeset
for help on using the changeset viewer.