Changeset 38763 in webkit for trunk/JavaScriptCore/interpreter/Interpreter.cpp
- Timestamp:
- Nov 25, 2008, 3:07:30 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/interpreter/Interpreter.cpp
r38688 r38763 84 84 // Preferred number of milliseconds between each timeout check 85 85 static const int preferredScriptCheckTimeInterval = 1000; 86 87 #if HAVE(COMPUTED_GOTO)88 static void* op_throw_end_indirect;89 static void* op_call_indirect;90 #endif91 86 92 87 #if ENABLE(JIT) … … 1324 1319 } 1325 1320 1321 static size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValue* baseValue, const PropertySlot& slot) 1322 { 1323 JSObject* o = asObject(baseValue); 1324 size_t count = 0; 1325 1326 while (slot.slotBase() != o) { 1327 JSValue* v = o->structure()->prototypeForLookup(callFrame); 1328 1329 // If we didn't find slotBase in baseValue's prototype chain, then baseValue 1330 // must be a proxy for another object. 1331 1332 if (v->isNull()) 1333 return 0; 1334 1335 o = asObject(v); 1336 1337 // Heavy access to a prototype is a good indication that it's not being 1338 // used as a dictionary. 1339 if (o->structure()->isDictionary()) { 1340 RefPtr<Structure> transition = Structure::fromDictionaryTransition(o->structure()); 1341 o->setStructure(transition.release()); 1342 asObject(baseValue)->structure()->setCachedPrototypeChain(0); 1343 } 1344 1345 ++count; 1346 } 1347 1348 ASSERT(count); 1349 return count; 1350 } 1351 1326 1352 NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot) 1327 1353 { … … 1404 1430 } 1405 1431 1406 size_t count = 0; 1407 JSObject* o = asObject(baseValue); 1408 while (slot.slotBase() != o) { 1409 JSValue* v = o->structure()->prototypeForLookup(callFrame); 1410 1411 // If we didn't find base in baseValue's prototype chain, then baseValue 1412 // must be a proxy for another object. 1413 if (v->isNull()) { 1414 vPC[0] = getOpcode(op_get_by_id_generic); 1415 return; 1416 } 1417 1418 o = asObject(v); 1419 1420 // Heavy access to a prototype is a good indication that it's not being 1421 // used as a dictionary. 1422 if (o->structure()->isDictionary()) { 1423 RefPtr<Structure> transition = Structure::fromDictionaryTransition(o->structure()); 1424 o->setStructure(transition.release()); 1425 asObject(baseValue)->structure()->setCachedPrototypeChain(0); 1426 } 1427 1428 ++count; 1432 size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); 1433 if (!count) { 1434 vPC[0] = getOpcode(op_get_by_id_generic); 1435 return; 1429 1436 } 1430 1437 … … 1463 1470 #undef ADD_OPCODE_ID 1464 1471 ASSERT(m_opcodeIDTable.size() == numOpcodeIDs); 1465 op_throw_end_indirect = &&op_throw_end;1466 op_call_indirect = &&op_call;1467 1472 #endif // HAVE(COMPUTED_GOTO) 1468 1473 return noValue(); … … 3315 3320 // We didn't find the blessed version of eval, so process this 3316 3321 // instruction as a normal function call. 3317 3318 #if HAVE(COMPUTED_GOTO)3319 // Hack around gcc performance quirk by performing an indirect goto3320 // in order to set the vPC -- attempting to do so directly results in a3321 // significant regression.3322 goto *op_call_indirect; // indirect goto -> op_call3323 #endif3324 3322 // fall through to op_call 3325 3323 } … … 3802 3800 return jsNull(); 3803 3801 } 3804 3805 #if HAVE(COMPUTED_GOTO)3806 // Hack around gcc performance quirk by performing an indirect goto3807 // in order to set the vPC -- attempting to do so directly results in a3808 // significant regression.3809 goto *op_throw_end_indirect; // indirect goto -> op_throw_end3810 }3811 op_throw_end: {3812 #endif3813 3802 3814 3803 vPC = handlerVPC; … … 4228 4217 } 4229 4218 4230 size_t count = 0; 4231 JSObject* o = asObject(baseValue); 4232 while (slot.slotBase() != o) { 4233 JSValue* v = o->structure()->prototypeForLookup(callFrame); 4234 4235 // If we didn't find slotBase in baseValue's prototype chain, then baseValue 4236 // must be a proxy for another object. 4237 4238 if (v->isNull()) { 4239 vPC[0] = getOpcode(op_get_by_id_generic); 4240 return; 4241 } 4242 4243 o = asObject(v); 4244 4245 // Heavy access to a prototype is a good indication that it's not being 4246 // used as a dictionary. 4247 if (o->structure()->isDictionary()) { 4248 RefPtr<Structure> transition = Structure::fromDictionaryTransition(o->structure()); 4249 o->setStructure(transition.release()); 4250 asObject(baseValue)->structure()->setCachedPrototypeChain(0); 4251 } 4252 4253 ++count; 4219 size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); 4220 if (!count) { 4221 vPC[0] = getOpcode(op_get_by_id_generic); 4222 return; 4254 4223 } 4255 4224 … … 4257 4226 if (!chain) 4258 4227 chain = cachePrototypeChain(callFrame, structure); 4259 4260 4228 ASSERT(chain); 4229 4261 4230 vPC[0] = getOpcode(op_get_by_id_chain); 4262 4231 vPC[4] = structure; … … 4621 4590 if (vPC[0].u.opcode == ARG_globalData->interpreter->getOpcode(op_get_by_id_self)) { 4622 4591 ASSERT(!stubInfo->stubRoutine); 4623 polymorphicStructureList = new PolymorphicAccessStructureList(vPC[ 4].u.structure, 0, vPC[5].u.operand, 0);4592 polymorphicStructureList = new PolymorphicAccessStructureList(vPC[5].u.operand, 0, vPC[4].u.structure); 4624 4593 4625 4594 vPC[0] = ARG_globalData->interpreter->getOpcode(op_get_by_id_self_list); … … 4643 4612 } 4644 4613 4614 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(Interpreter* interpreter, StructureStubInfo* stubInfo, Instruction* vPC, int& listIndex) 4615 { 4616 PolymorphicAccessStructureList* prototypeStructureList; 4617 listIndex = 1; 4618 4619 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { 4620 prototypeStructureList = new PolymorphicAccessStructureList(vPC[6].u.operand, stubInfo->stubRoutine, vPC[4].u.structure, vPC[5].u.structure); 4621 stubInfo->stubRoutine = 0; 4622 4623 vPC[0] = interpreter->getOpcode(op_get_by_id_proto_list); 4624 vPC[4] = prototypeStructureList; 4625 vPC[5] = 2; 4626 } else if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { 4627 prototypeStructureList = new PolymorphicAccessStructureList(vPC[6].u.operand, stubInfo->stubRoutine, vPC[4].u.structure, vPC[5].u.structureChain); 4628 stubInfo->stubRoutine = 0; 4629 4630 vPC[0] = interpreter->getOpcode(op_get_by_id_proto_list); 4631 vPC[4] = prototypeStructureList; 4632 vPC[5] = 2; 4633 } else { 4634 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list)); 4635 prototypeStructureList = vPC[4].u.polymorphicStructures; 4636 listIndex = vPC[5].u.operand; 4637 vPC[5] = listIndex + 1; 4638 4639 ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE); 4640 } 4641 4642 return prototypeStructureList; 4643 } 4644 4645 4645 JSValue* Interpreter::cti_op_get_by_id_proto_list(CTI_ARGS) 4646 4646 { … … 4655 4655 CHECK_FOR_EXCEPTION(); 4656 4656 4657 if ( baseValue->isObject()4658 && slot.isCacheable()4659 && !asCell(baseValue)->structure()->isDictionary()4660 && slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {4661 4662 JSCell* baseCell = asCell(baseValue);4663 Structure* structure = baseCell->structure();4664 CodeBlock* codeBlock = callFrame->codeBlock();4665 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); 4666 Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;4667 4668 ASSERT(slot.slotBase()->isObject()); 4669 4670 JSObject* slotBaseObject = asObject(slot.slotBase());4671 4657 if (!baseValue->isObject() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) { 4658 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); 4659 return result; 4660 } 4661 4662 Structure* structure = asCell(baseValue)->structure(); 4663 CodeBlock* codeBlock = callFrame->codeBlock(); 4664 Instruction* vPC = codeBlock->instructions.begin() + codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS); 4665 4666 ASSERT(slot.slotBase()->isObject()); 4667 JSObject* slotBaseObject = asObject(slot.slotBase()); 4668 4669 if (slot.slotBase() == baseValue) 4670 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); 4671 else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) { 4672 4672 // Heavy access to a prototype is a good indication that it's not being 4673 4673 // used as a dictionary. … … 4679 4679 4680 4680 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(CTI_RETURN_ADDRESS); 4681 4682 PolymorphicAccessStructureList* prototypeStructureList; 4683 int listIndex = 1; 4684 4685 if (vPC[0].u.opcode == ARG_globalData->interpreter->getOpcode(op_get_by_id_proto)) { 4686 prototypeStructureList = new PolymorphicAccessStructureList(vPC[4].u.structure, vPC[5].u.structure, vPC[6].u.operand, stubInfo->stubRoutine); 4687 stubInfo->stubRoutine = 0; 4688 4689 vPC[0] = ARG_globalData->interpreter->getOpcode(op_get_by_id_proto_list); 4690 vPC[4] = prototypeStructureList; 4691 vPC[5] = 2; 4692 } else { 4693 prototypeStructureList = vPC[4].u.polymorphicStructures; 4694 listIndex = vPC[5].u.operand; 4695 4696 vPC[5] = listIndex + 1; 4697 } 4681 int listIndex; 4682 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(ARG_globalData->interpreter, stubInfo, vPC, listIndex); 4698 4683 4699 4684 JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset()); … … 4701 4686 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 4702 4687 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full)); 4703 } else { 4688 } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) { 4689 StructureChain* chain = structure->cachedPrototypeChain(); 4690 if (!chain) 4691 chain = cachePrototypeChain(callFrame, structure); 4692 ASSERT(chain); 4693 4694 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(CTI_RETURN_ADDRESS); 4695 int listIndex; 4696 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(ARG_globalData->interpreter, stubInfo, vPC, listIndex); 4697 4698 JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, chain, count, slot.cachedOffset()); 4699 4700 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 4701 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full)); 4702 } else 4704 4703 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); 4705 } 4704 4706 4705 return result; 4707 4706 } … … 4720 4719 4721 4720 JSValue* Interpreter::cti_op_get_by_id_proto_fail(CTI_ARGS) 4722 {4723 CTI_STACK_HACK();4724 4725 JSValue* baseValue = ARG_src1;4726 PropertySlot slot(baseValue);4727 JSValue* result = baseValue->get(ARG_callFrame, *ARG_id2, slot);4728 4729 CHECK_FOR_EXCEPTION_AT_END();4730 return result;4731 }4732 4733 JSValue* Interpreter::cti_op_get_by_id_chain_fail(CTI_ARGS)4734 4721 { 4735 4722 CTI_STACK_HACK();
Note:
See TracChangeset
for help on using the changeset viewer.