Changeset 222827 in webkit for trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp
- Timestamp:
- Oct 3, 2017, 6:53:18 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp
r221954 r222827 56 56 } 57 57 58 AccessCase::AccessCase(VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet )58 AccessCase::AccessCase(VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain) 59 59 : m_type(type) 60 60 , m_offset(offset) 61 , m_polyProtoAccessChain(WTFMove(prototypeAccessChain)) 61 62 { 62 63 m_structure.setMayBeNull(vm, owner, structure); … … 64 65 } 65 66 66 std::unique_ptr<AccessCase> AccessCase::create(VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet )67 std::unique_ptr<AccessCase> AccessCase::create(VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain) 67 68 { 68 69 switch (type) { 69 70 case InHit: 70 71 case InMiss: 72 break; 71 73 case ArrayLength: 72 74 case StringLength: … … 75 77 case ModuleNamespaceLoad: 76 78 case Replace: 79 RELEASE_ASSERT(!prototypeAccessChain); 77 80 break; 78 81 default: 79 ASSERT_NOT_REACHED();82 RELEASE_ASSERT_NOT_REACHED(); 80 83 }; 81 84 82 return std::unique_ptr<AccessCase>(new AccessCase(vm, owner, type, offset, structure, conditionSet ));85 return std::unique_ptr<AccessCase>(new AccessCase(vm, owner, type, offset, structure, conditionSet, WTFMove(prototypeAccessChain))); 83 86 } 84 87 85 88 std::unique_ptr<AccessCase> AccessCase::create( 86 89 VM& vm, JSCell* owner, PropertyOffset offset, Structure* oldStructure, Structure* newStructure, 87 const ObjectPropertyConditionSet& conditionSet )90 const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain) 88 91 { 89 92 RELEASE_ASSERT(oldStructure == newStructure->previousID()); … … 97 100 } 98 101 99 return std::unique_ptr<AccessCase>(new AccessCase(vm, owner, Transition, offset, newStructure, conditionSet ));102 return std::unique_ptr<AccessCase>(new AccessCase(vm, owner, Transition, offset, newStructure, conditionSet, WTFMove(prototypeAccessChain))); 100 103 } 101 104 … … 136 139 137 140 if ((structure() && structure()->needImpurePropertyWatchpoint()) 138 || m_conditionSet.needImpurePropertyWatchpoint()) 141 || m_conditionSet.needImpurePropertyWatchpoint() 142 || (m_polyProtoAccessChain && m_polyProtoAccessChain->needImpurePropertyWatchpoint())) 139 143 result.append(vm.ensureWatchpointSetForImpureProperty(ident)); 140 144 … … 150 154 { 151 155 if (viaProxy()) 156 return false; 157 158 if (m_polyProtoAccessChain) 152 159 return false; 153 160 … … 211 218 } 212 219 default: 220 if (other.type() != type()) 221 return false; 222 223 if (m_polyProtoAccessChain) { 224 if (!other.m_polyProtoAccessChain) 225 return false; 226 // This is the only check we need since PolyProtoAccessChain contains the base structure. 227 // If we ever change it to contain only the prototype chain, we'll also need to change 228 // this to check the base structure. 229 return structure() == other.structure() 230 && *m_polyProtoAccessChain == *other.m_polyProtoAccessChain; 231 } 232 213 233 if (!guardedByStructureCheck() || !other.guardedByStructureCheck()) 214 234 return false; … … 220 240 void AccessCase::dump(PrintStream& out) const 221 241 { 222 out.print( m_type, ":(");242 out.print("\n", m_type, ":("); 223 243 224 244 CommaPrinter comma; 225 245 226 246 out.print(comma, m_state); 227 228 if (m_type == Transition)229 out.print(comma, "structure = ", pointerDump(structure()), " -> ", pointerDump(newStructure()));230 else if (m_structure)231 out.print(comma, "structure = ", pointerDump(m_structure.get()));232 247 233 248 if (isValidOffset(m_offset)) … … 236 251 out.print(comma, "conditions = ", m_conditionSet); 237 252 253 if (m_polyProtoAccessChain) { 254 out.print(comma, "prototype access chain = "); 255 m_polyProtoAccessChain->dump(structure(), out); 256 } else { 257 if (m_type == Transition) 258 out.print(comma, "structure = ", pointerDump(structure()), " -> ", pointerDump(newStructure())); 259 else if (m_structure) 260 out.print(comma, "structure = ", pointerDump(m_structure.get())); 261 } 262 238 263 dumpImpl(out, comma); 239 264 out.print(")"); … … 244 269 if (m_structure && !Heap::isMarked(m_structure.get())) 245 270 return false; 271 if (m_polyProtoAccessChain) { 272 for (Structure* structure : m_polyProtoAccessChain->chain()) { 273 if (!Heap::isMarked(structure)) 274 return false; 275 } 276 } 246 277 if (!m_conditionSet.areStillLive()) 247 278 return false; … … 274 305 result &= m_structure->markIfCheap(visitor); 275 306 307 if (m_polyProtoAccessChain) { 308 for (Structure* structure : m_polyProtoAccessChain->chain()) 309 result &= structure->markIfCheap(visitor); 310 } 311 276 312 switch (m_type) { 277 313 case Transition: … … 373 409 374 410 default: { 375 if (viaProxy()) { 376 fallThrough.append( 377 jit.branch8( 378 CCallHelpers::NotEqual, 379 CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), 380 CCallHelpers::TrustedImm32(PureForwardingProxyType))); 381 382 jit.loadPtr(CCallHelpers::Address(baseGPR, JSProxy::targetOffset()), scratchGPR); 383 384 fallThrough.append( 385 jit.branchStructure( 386 CCallHelpers::NotEqual, 387 CCallHelpers::Address(scratchGPR, JSCell::structureIDOffset()), 388 structure())); 411 if (m_polyProtoAccessChain) { 412 GPRReg baseForAccessGPR = state.scratchGPR; 413 jit.move(state.baseGPR, baseForAccessGPR); 414 m_polyProtoAccessChain->forEach(structure(), [&] (Structure* structure, bool atEnd) { 415 fallThrough.append( 416 jit.branchStructure( 417 CCallHelpers::NotEqual, 418 CCallHelpers::Address(baseForAccessGPR, JSCell::structureIDOffset()), 419 structure)); 420 if (atEnd) { 421 if ((m_type == Miss || m_type == InMiss || m_type == Transition) && structure->hasPolyProto()) { 422 // For a Miss/InMiss/Transition, we must ensure we're at the end when the last item is poly proto. 423 // Transitions must do this because they need to verify there isn't a setter in the chain. 424 // Miss/InMiss need to do this to ensure there isn't a new item at the end of the chain that 425 // has the property. 426 PropertyOffset polyProtoOffset = structure->polyProtoOffset(); 427 RELEASE_ASSERT(isInlineOffset(polyProtoOffset)); 428 #if USE(JSVALUE64) 429 jit.load64(MacroAssembler::Address(baseForAccessGPR, offsetRelativeToBase(polyProtoOffset)), baseForAccessGPR); 430 fallThrough.append(jit.branch64(CCallHelpers::NotEqual, baseForAccessGPR, CCallHelpers::TrustedImm64(ValueNull))); 431 #else 432 jit.load32(MacroAssembler::Address(baseForAccessGPR, offsetRelativeToBase(polyProtoOffset) + PayloadOffset), baseForAccessGPR); 433 fallThrough.append(jit.branchTestPtr(CCallHelpers::NonZero, baseForAccessGPR)); 434 #endif 435 } 436 } else { 437 if (structure->hasMonoProto()) { 438 JSValue prototype = structure->prototypeForLookup(state.m_globalObject); 439 RELEASE_ASSERT(prototype.isObject()); 440 jit.move(CCallHelpers::TrustedImmPtr(asObject(prototype)), baseForAccessGPR); 441 } else { 442 RELEASE_ASSERT(structure->isObject()); // Primitives must have a stored prototype. We use prototypeForLookup for them. 443 PropertyOffset polyProtoOffset = structure->polyProtoOffset(); 444 RELEASE_ASSERT(isInlineOffset(polyProtoOffset)); 445 #if USE(JSVALUE64) 446 jit.load64(MacroAssembler::Address(baseForAccessGPR, offsetRelativeToBase(polyProtoOffset)), baseForAccessGPR); 447 fallThrough.append(jit.branch64(CCallHelpers::Equal, baseForAccessGPR, CCallHelpers::TrustedImm64(ValueNull))); 448 #else 449 jit.load32(MacroAssembler::Address(baseForAccessGPR, offsetRelativeToBase(polyProtoOffset) + PayloadOffset), baseForAccessGPR); 450 fallThrough.append(jit.branchTestPtr(CCallHelpers::Zero, baseForAccessGPR)); 451 #endif 452 } 453 } 454 }); 389 455 } else { 390 fallThrough.append( 391 jit.branchStructure( 392 CCallHelpers::NotEqual, 393 CCallHelpers::Address(baseGPR, JSCell::structureIDOffset()), 394 structure())); 456 if (viaProxy()) { 457 fallThrough.append( 458 jit.branch8( 459 CCallHelpers::NotEqual, 460 CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), 461 CCallHelpers::TrustedImm32(PureForwardingProxyType))); 462 463 jit.loadPtr(CCallHelpers::Address(baseGPR, JSProxy::targetOffset()), scratchGPR); 464 465 fallThrough.append( 466 jit.branchStructure( 467 CCallHelpers::NotEqual, 468 CCallHelpers::Address(scratchGPR, JSCell::structureIDOffset()), 469 structure())); 470 } else { 471 fallThrough.append( 472 jit.branchStructure( 473 CCallHelpers::NotEqual, 474 CCallHelpers::Address(baseGPR, JSCell::structureIDOffset()), 475 structure())); 476 } 395 477 } 396 478 break; … … 429 511 430 512 for (const ObjectPropertyCondition& condition : m_conditionSet) { 513 RELEASE_ASSERT(!m_polyProtoAccessChain); 514 431 515 Structure* structure = condition.object()->structure(); 432 516 … … 505 589 506 590 GPRReg baseForAccessGPR; 507 if ( !m_conditionSet.isEmpty()) {508 jit.move(509 CCallHelpers::TrustedImmPtr(alternateBase()),510 scratchGPR);591 if (m_polyProtoAccessChain) { 592 // This isn't pretty, but we know we got here via generateWithGuard, 593 // and it left the baseForAccess inside scratchGPR. We could re-derive the base, 594 // but it'd require emitting the same code to load the base twice. 511 595 baseForAccessGPR = scratchGPR; 512 } else 513 baseForAccessGPR = baseForGetGPR; 596 } else { 597 if (!m_conditionSet.isEmpty()) { 598 jit.move( 599 CCallHelpers::TrustedImmPtr(alternateBase()), scratchGPR); 600 baseForAccessGPR = scratchGPR; 601 } else 602 baseForAccessGPR = baseForGetGPR; 603 } 514 604 515 605 GPRReg loadedValueGPR = InvalidGPRReg; … … 1017 1107 case IntrinsicGetter: { 1018 1108 RELEASE_ASSERT(isValidOffset(offset())); 1019 1109 1020 1110 // We need to ensure the getter value does not move from under us. Note that GetterSetters 1021 1111 // are immutable so we just need to watch the property not any value inside it.
Note:
See TracChangeset
for help on using the changeset viewer.