Changeset 34372 in webkit for trunk/JavaScriptCore/VM/Machine.cpp
- Timestamp:
- Jun 4, 2008, 10:36:55 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/VM/Machine.cpp
r34371 r34372 81 81 { 82 82 int scopeDepth = 0; 83 ScopeChainIterator iter = sc.begin(); 84 ScopeChainIterator end = sc.end(); 83 ScopeChainIterator iter = sc.begin(); 84 ScopeChainIterator end = sc.end(); 85 85 while (!(*iter)->isVariableObject()) { 86 86 ++iter; … … 89 89 return scopeDepth; 90 90 } 91 91 92 92 static inline bool jsLess(ExecState* exec, JSValue* v1, JSValue* v2) 93 93 { … … 219 219 return false; 220 220 } 221 221 222 222 static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue) 223 223 { … … 225 225 int property = (vPC + 2)->u.operand; 226 226 int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain; 227 227 228 228 ScopeChainIterator iter = scopeChain->begin(); 229 229 ScopeChainIterator end = scopeChain->end(); … … 280 280 int propDst = (vPC + 2)->u.operand; 281 281 int property = (vPC + 3)->u.operand; 282 282 283 283 ScopeChainIterator iter = scopeChain->begin(); 284 284 ScopeChainIterator end = scopeChain->end(); 285 285 286 286 // FIXME: add scopeDepthIsZero optimization 287 287 288 288 ASSERT(iter != end); 289 289 290 290 Identifier& ident = codeBlock->identifiers[property]; 291 291 JSObject* base; … … 298 298 if (exceptionValue) 299 299 return false; 300 r[propDst].u.jsValue = result; 300 r[propDst].u.jsValue = result; 301 301 r[baseDst].u.jsValue = base; 302 302 return true; … … 304 304 ++iter; 305 305 } while (iter != end); 306 306 307 307 exceptionValue = createUndefinedVariableError(exec, ident); 308 308 return false; … … 317 317 ScopeChainIterator iter = scopeChain->begin(); 318 318 ScopeChainIterator end = scopeChain->end(); 319 319 320 320 // FIXME: add scopeDepthIsZero optimization 321 321 322 322 ASSERT(iter != end); 323 323 324 324 Identifier& ident = codeBlock->identifiers[property]; 325 325 JSObject* base; … … 340 340 if (exceptionValue) 341 341 return false; 342 342 343 343 r[baseDst].u.jsValue = thisObj; 344 344 r[funcDst].u.jsValue = result; … … 385 385 } 386 386 r = (*registerBase) + registerOffset; 387 387 388 388 int omittedArgCount = newCodeBlock->numParameters - argc; 389 389 Register* endOfParams = r - newCodeBlock->numVars; … … 400 400 } 401 401 r = (*registerBase) + registerOffset; 402 402 403 403 Register* it = r - newCodeBlock->numLocals - Machine::CallFrameHeaderSize - shift; 404 404 Register* end = it + Machine::CallFrameHeaderSize + newCodeBlock->numParameters; … … 436 436 437 437 JSValue* program = r[argv + 1].u.jsValue; 438 438 439 439 if (!program->isString()) 440 440 return program; 441 441 442 442 Profiler** profiler = Profiler::enabledProfilerReference(); 443 443 if (*profiler) … … 448 448 UString errMsg; 449 449 RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(static_cast<StringImp*>(program)->value()), &sourceId, &errLine, &errMsg); 450 450 451 451 if (!evalNode) { 452 452 exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL); … … 491 491 printf(" use | address | value \n"); 492 492 printf("----------------------------------------\n"); 493 493 494 494 const Register* it; 495 495 const Register* end; 496 496 497 497 if (isGlobalCallFrame(registerFile->basePointer(), r)) { 498 498 it = r - registerFile->numGlobalSlots(); … … 515 515 printf("----------------------------------------\n"); 516 516 } 517 517 518 518 end = it + codeBlock->numParameters; 519 519 if (it != end) { … … 559 559 CodeBlock* oldCodeBlock = codeBlock; 560 560 Register* callFrame = r - oldCodeBlock->numLocals - CallFrameHeaderSize; 561 561 562 562 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) { 563 563 DebuggerCallFrame debuggerCallFrame(this, exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase); … … 577 577 if (oldCodeBlock->needsFullScopeChain) 578 578 scopeChain->deref(); 579 579 580 580 if (isGlobalCallFrame(registerBase, r)) 581 581 return false; … … 620 620 // Calculate an exception handler vPC, unwinding call frames as necessary. 621 621 622 int scopeDepth; 622 int scopeDepth; 623 623 Instruction* handlerVPC; 624 624 625 while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) 625 while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) { 626 626 if (!unwindCallFrame(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r)) 627 627 return 0; 628 } 628 629 629 630 // Now unwind the scope chain within the exception handler's call frame. 630 631 631 632 ScopeChain sc(scopeChain); 632 633 int scopeDelta = depth(sc) - scopeDepth; … … 659 660 660 661 r[ProgramCodeThisRegister].u.jsValue = thisObj; 661 662 662 663 if (codeBlock->needsFullScopeChain) 663 664 scopeChain = scopeChain->copy(); … … 692 693 int argv = CallFrameHeaderSize; 693 694 int argc = args.size() + 1; // implicit "this" parameter 694 695 695 696 size_t oldSize = registerFile->size(); 696 697 if (!registerFile->grow(oldSize + CallFrameHeaderSize + argc)) { … … 698 699 return 0; 699 700 } 700 701 701 702 Register** registerBase = registerFile->basePointer(); 702 703 int registerOffset = oldSize; 703 704 int callFrameOffset = registerOffset; 704 705 Register* callFrame = (*registerBase) + callFrameOffset; 705 706 706 707 // put args in place, including "this" 707 708 Register* dst = callFrame + CallFrameHeaderSize; 708 709 (*dst).u.jsValue = thisObj; 709 710 710 711 List::const_iterator end = args.end(); 711 712 for (List::const_iterator it = args.begin(); it != end; ++it) … … 722 723 } 723 724 724 scopeChain = scopeChainForCall(functionBodyNode, newCodeBlock, scopeChain, registerBase, r); 725 scopeChain = scopeChainForCall(functionBodyNode, newCodeBlock, scopeChain, registerBase, r); 725 726 726 727 ExecState newExec(exec, this, registerFile, scopeChain, callFrameOffset); 727 728 728 729 Profiler** profiler = Profiler::enabledProfilerReference(); 729 730 if (*profiler) … … 746 747 747 748 EvalCodeBlock* codeBlock = &evalNode->code(scopeChain); 748 749 749 750 JSVariableObject* variableObject; 750 751 for (ScopeChainNode* node = scopeChain; ; node = node->next) { … … 755 756 } 756 757 } 757 758 758 759 const Node::VarStack& varStack = codeBlock->ownerNode->varStack(); 759 760 Node::VarStack::const_iterator varStackEnd = varStack.end(); … … 763 764 variableObject->put(exec, ident, jsUndefined()); 764 765 } 765 766 766 767 const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack(); 767 768 Node::FunctionStack::const_iterator functionStackEnd = functionStack.end(); 768 769 for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) 769 770 variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain)); 770 771 771 772 size_t oldSize = registerFile->size(); 772 773 size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numTemporaries + CallFrameHeaderSize; … … 777 778 778 779 Register* callFrame = *registerFile->basePointer() + registerOffset; 779 780 780 781 // put call frame in place, using a 0 codeBlock to indicate a built-in caller 781 782 initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, 0, 0, 0, 0); … … 889 890 JSValue** k = codeBlock->jsValues.data(); 890 891 Profiler** enabledProfilerReference = Profiler::enabledProfilerReference(); 891 892 892 893 #if HAVE(COMPUTED_GOTO) 893 894 // Yet another hack around GCC's various foibles, in this case fetching the … … 922 923 #define BEGIN_OPCODE(opcode) case opcode: 923 924 #endif 924 while (1) // iterator loop begins925 while (1) // iterator loop begins 925 926 switch (vPC->u.opcode) 926 927 #endif … … 934 935 int src = (++vPC)->u.operand; 935 936 r[dst].u.jsValue = k[src]; 936 937 937 938 ++vPC; 938 939 NEXT_OPCODE; … … 946 947 int dst = (++vPC)->u.operand; 947 948 r[dst].u.jsValue = scopeChain->globalObject()->objectConstructor()->construct(exec, exec->emptyList()); 948 949 949 950 ++vPC; 950 951 NEXT_OPCODE; … … 958 959 int dst = (++vPC)->u.operand; 959 960 r[dst].u.jsValue = scopeChain->globalObject()->arrayConstructor()->construct(exec, exec->emptyList()); 960 961 961 962 ++vPC; 962 963 NEXT_OPCODE; … … 1046 1047 else 1047 1048 dst = jsBoolean(strictEqual(src1, src2)); 1048 1049 1049 1050 ++vPC; 1050 1051 NEXT_OPCODE; … … 1117 1118 VM_CHECK_EXCEPTION(); 1118 1119 r[srcDst].u.jsValue = result; 1119 1120 1120 1121 ++vPC; 1121 1122 NEXT_OPCODE; … … 1281 1282 /* mod dst(r) dividend(r) divisor(r) 1282 1283 1283 Divides register dividend (converted to number) by 1284 Divides register dividend (converted to number) by 1284 1285 register divisor (converted to number), and puts the 1285 1286 remainder in register dst. … … 1334 1335 } 1335 1336 dst = result; 1336 1337 1337 1338 ++vPC; 1338 1339 NEXT_OPCODE; … … 1356 1357 } 1357 1358 dst = result; 1358 1359 1359 1360 ++vPC; 1360 1361 NEXT_OPCODE; … … 1378 1379 } 1379 1380 dst = result; 1380 1381 1381 1382 ++vPC; 1382 1383 NEXT_OPCODE; … … 1400 1401 } 1401 1402 dst = result; 1402 1403 1403 1404 ++vPC; 1404 1405 NEXT_OPCODE; … … 1422 1423 } 1423 1424 dst = result; 1424 1425 1425 1426 ++vPC; 1426 1427 NEXT_OPCODE; … … 1444 1445 } 1445 1446 dst = result; 1446 1447 1447 1448 ++vPC; 1448 1449 NEXT_OPCODE; … … 1483 1484 Tests whether register value is an instance of register 1484 1485 constructor, and puts the boolean result in register dst. 1485 1486 1486 1487 Raises an exception if register constructor is not an 1487 1488 object. … … 1520 1521 Tests whether register base has a property named register 1521 1522 property, and puts the boolean result in register dst. 1522 1523 1523 1524 Raises an exception if register constructor is not an 1524 1525 object. … … 1563 1564 BEGIN_OPCODE(op_resolve_skip) { 1564 1565 /* resolve_skip dst(r) property(id) skip(n) 1565 1566 1566 1567 Looks up the property named by identifier property in the 1567 1568 scope chain skipping the top 'skip' levels, and writes the resulting … … 1570 1571 if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue))) 1571 1572 goto vm_throw; 1572 1573 1573 1574 vPC += 4; 1574 1575 1575 1576 NEXT_OPCODE; 1576 1577 } 1577 1578 BEGIN_OPCODE(op_get_scoped_var) { 1578 1579 /* get_scoped_var dst(r) index(n) skip(n) 1579 1580 1580 1581 Loads the contents of the index-th local from the scope skip nodes from 1581 1582 the top of the scope chain, and places it in register dst … … 1584 1585 int index = (++vPC)->u.operand; 1585 1586 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain; 1586 1587 1587 1588 ScopeChainIterator iter = scopeChain->begin(); 1588 1589 ScopeChainIterator end = scopeChain->end(); … … 1592 1593 ASSERT(iter != end); 1593 1594 } 1594 1595 1595 1596 ASSERT((*iter)->isVariableObject()); 1596 1597 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); … … 1606 1607 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain; 1607 1608 int value = (++vPC)->u.operand; 1608 1609 1609 1610 ScopeChainIterator iter = scopeChain->begin(); 1610 1611 ScopeChainIterator end = scopeChain->end(); … … 1614 1615 ASSERT(iter != end); 1615 1616 } 1616 1617 1617 1618 ASSERT((*iter)->isVariableObject()); 1618 1619 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); … … 1700 1701 Sets register value on register base as the property named 1701 1702 by identifier property. Base is converted to object first. 1702 1703 1703 1704 Unlike many opcodes, this one does not write any output to 1704 1705 the register file. … … 1710 1711 int registerOffset = r - (*registerBase); 1711 1712 #endif 1712 1713 1713 1714 Identifier& ident = codeBlock->identifiers[property]; 1714 1715 r[base].u.jsValue->put(exec, ident, r[value].u.jsValue); 1715 1716 ASSERT(registerOffset == (r - (*registerBase))); 1716 1717 1717 1718 VM_CHECK_EXCEPTION(); 1718 1719 ++vPC; … … 1732 1733 1733 1734 JSObject* baseObj = r[base].u.jsValue->toObject(exec); 1734 1735 1735 1736 Identifier& ident = codeBlock->identifiers[property]; 1736 1737 JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident)); … … 1753 1754 1754 1755 JSValue* baseValue = r[base].u.jsValue; 1755 1756 1756 1757 JSValue* subscript = r[property].u.jsValue; 1757 1758 JSValue* result; … … 1772 1773 result = baseObj->get(exec, property); 1773 1774 } 1774 1775 1775 1776 VM_CHECK_EXCEPTION(); 1776 1777 r[dst].u.jsValue = result; … … 1785 1786 first. register property is nominally converted to string 1786 1787 but numbers are treated more efficiently. 1787 1788 1788 1789 Unlike many opcodes, this one does not write any output to 1789 1790 the register file. … … 1794 1795 1795 1796 JSValue* baseValue = r[base].u.jsValue; 1796 1797 1797 1798 JSValue* subscript = r[property].u.jsValue; 1798 1799 … … 1813 1814 baseObj->put(exec, property, r[value].u.jsValue); 1814 1815 } 1815 1816 1816 1817 VM_CHECK_EXCEPTION(); 1817 1818 ++vPC; … … 1843 1844 result = jsBoolean(baseObj->deleteProperty(exec, property)); 1844 1845 } 1845 1846 1846 1847 VM_CHECK_EXCEPTION(); 1847 1848 r[dst].u.jsValue = result; … … 1856 1857 object first. register property is nominally converted to 1857 1858 string but numbers are treated more efficiently. 1858 1859 1859 1860 Unlike many opcodes, this one does not write any output to 1860 1861 the register file. … … 1873 1874 BEGIN_OPCODE(op_jmp) { 1874 1875 /* jmp target(offset) 1875 1876 1876 1877 Jumps unconditionally to offset target from the current 1877 1878 instruction. … … 1884 1885 BEGIN_OPCODE(op_jtrue) { 1885 1886 /* jtrue cond(r) target(offset) 1886 1887 1887 1888 Jumps to offset target from the current instruction, if and 1888 1889 only if register cond converts to boolean as true. … … 1900 1901 BEGIN_OPCODE(op_jfalse) { 1901 1902 /* jfalse cond(r) target(offset) 1902 1903 1903 1904 Jumps to offset target from the current instruction, if and 1904 1905 only if register cond converts to boolean as false. … … 1966 1967 JSValue* funcVal = r[func].u.jsValue; 1967 1968 JSValue* baseVal = r[thisVal].u.jsValue; 1968 1969 1969 1970 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) { 1970 1971 int registerOffset = r - (*registerBase); … … 1983 1984 1984 1985 r[dst].u.jsValue = result; 1985 1986 1986 1987 ++vPC; 1987 1988 NEXT_OPCODE; 1988 1989 } 1989 1990 1990 1991 // We didn't find the blessed version of eval, so reset vPC and process 1991 1992 // this instruction as a normal function call, supplying the proper 'this' … … 2044 2045 int firstArg = (++vPC)->u.operand; 2045 2046 int argCount = (++vPC)->u.operand; 2046 2047 2047 2048 JSValue* v = r[func].u.jsValue; 2048 2049 2049 2050 CallData callData; 2050 2051 CallType callType = v->getCallData(callData); 2051 2052 2052 2053 if (callType == CallTypeJS) { 2053 2054 if (*enabledProfilerReference) … … 2140 2141 returnValue = thisObject; 2141 2142 } 2142 2143 2143 2144 codeBlock = callFrame[CallerCodeBlock].u.codeBlock; 2144 2145 if (!codeBlock) 2145 2146 return returnValue; 2146 2147 2147 2148 k = codeBlock->jsValues.data(); 2148 2149 vPC = callFrame[ReturnVPC].u.vPC; … … 2254 2255 JSObject* o = v->toObject(exec); 2255 2256 VM_CHECK_EXCEPTION(); 2256 2257 2257 2258 setScopeChain(exec, scopeChain, scopeChain->push(o)); 2258 2259 … … 2318 2319 int count = (++vPC)->u.operand; 2319 2320 int target = (++vPC)->u.operand; 2320 2321 2321 2322 ScopeChainNode* tmp = scopeChain; 2322 2323 while (count--) 2323 2324 tmp = tmp->pop(); 2324 2325 setScopeChain(exec, scopeChain, tmp); 2325 2326 2326 2327 vPC += target; 2327 2328 NEXT_OPCODE; … … 2385 2386 int type = (++vPC)->u.operand; 2386 2387 int message = (++vPC)->u.operand; 2387 2388 2388 2389 r[dst].u.jsValue = Error::create(exec, (ErrorType)type, k[message]->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL()); 2389 2390 2390 2391 ++vPC; 2391 2392 NEXT_OPCODE; … … 2407 2408 BEGIN_OPCODE(op_put_getter) { 2408 2409 /* put_getter base(r) property(id) function(r) 2409 2410 2410 2411 Sets register function on register base as the getter named 2411 2412 by identifier property. Base and function are assumed to be 2412 2413 objects as this op should only be used for getters defined 2413 2414 in object literal form. 2414 2415 2415 2416 Unlike many opcodes, this one does not write any output to 2416 2417 the register file. … … 2419 2420 int property = (++vPC)->u.operand; 2420 2421 int function = (++vPC)->u.operand; 2421 2422 2422 2423 ASSERT(r[base].u.jsValue->isObject()); 2423 2424 JSObject* baseObj = static_cast<JSObject*>(r[base].u.jsValue); … … 2431 2432 BEGIN_OPCODE(op_put_setter) { 2432 2433 /* put_setter base(r) property(id) function(r) 2433 2434 2434 2435 Sets register function on register base as the setter named 2435 2436 by identifier property. Base and function are assumed to be 2436 2437 objects as this op should only be used for setters defined 2437 2438 in object literal form. 2438 2439 2439 2440 Unlike many opcodes, this one does not write any output to 2440 2441 the register file. … … 2443 2444 int property = (++vPC)->u.operand; 2444 2445 int function = (++vPC)->u.operand; 2445 2446 2446 2447 ASSERT(r[base].u.jsValue->isObject()); 2447 2448 JSObject* baseObj = static_cast<JSObject*>(r[base].u.jsValue); … … 2449 2450 ASSERT(r[function].u.jsValue->isObject()); 2450 2451 baseObj->defineSetter(exec, ident, static_cast<JSObject* >(r[function].u.jsValue)); 2451 2452 2452 2453 ++vPC; 2453 2454 NEXT_OPCODE; … … 2455 2456 BEGIN_OPCODE(op_jsr) { 2456 2457 /* jsr retAddrDst(r) target(offset) 2457 2458 2458 2459 Places the address of the next instruction into the retAddrDst 2459 2460 register and jumps to offset target from the current instruction. … … 2468 2469 BEGIN_OPCODE(op_sret) { 2469 2470 /* sret retAddrSrc(r) 2470 2471 2471 2472 Jumps to the address stored in the retAddrSrc register. This 2472 2473 differs from op_jmp because the target address is stored in a … … 2479 2480 BEGIN_OPCODE(op_debug) { 2480 2481 /* debug debugHookID(n) firstLine(n) lastLine(n) 2481 2482 2482 2483 Notifies the debugger of the current state of execution. This opcode 2483 2484 is only generated while the debugger is attached. … … 2502 2503 vPC = handlerVPC; 2503 2504 NEXT_OPCODE; 2504 } 2505 } 2505 2506 } 2506 2507 #undef NEXT_OPCODE
Note:
See TracChangeset
for help on using the changeset viewer.