Changeset 239612 in webkit
- Timestamp:
- Jan 4, 2019 9:04:09 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r239605 r239612 1 2019-01-02 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 3 [JSC] Optimize Object.prototype.toString 4 https://bugs.webkit.org/show_bug.cgi?id=193031 5 6 Reviewed by Saam Barati. 7 8 * stress/object-tostring-changed-proto.js: Added. 9 (shouldBe): 10 (test): 11 * stress/object-tostring-changed.js: Added. 12 (shouldBe): 13 (test): 14 * stress/object-tostring-misc.js: Added. 15 (shouldBe): 16 (test): 17 (i.switch): 18 * stress/object-tostring-other.js: Added. 19 (shouldBe): 20 (test): 21 * stress/object-tostring-untyped.js: Added. 22 (shouldBe): 23 (test): 24 (i.switch): 25 1 26 2019-01-03 Ross Kirsling <ross.kirsling@sony.com> 2 27 -
trunk/Source/JavaScriptCore/ChangeLog
r239595 r239612 1 2019-01-02 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 3 [JSC] Optimize Object.prototype.toString 4 https://bugs.webkit.org/show_bug.cgi?id=193031 5 6 Reviewed by Saam Barati. 7 8 Object.prototype.toString is frequently used for type checking. 9 It is called many times in wtb-lebab.js. This patch optimizes 10 Object.prototype.toString by the following two optimizations. 11 12 1. We should emit code looking up cached to string in DFG and FTL. 13 14 toString's result is cached in the Structure. We emit a fast path code 15 in DFG and FTL to lookup this cache. 16 17 2. We should not create objects for primitive values in major cases. 18 19 When Object.prototype.toString(primitive) is called, this primitive is converted 20 to an object by calling ToObject. But if the result is appropriately cached in 21 the Structure, we should get it in the fast path without creating this object. 22 When converting primitives to objects, Structures used in these newly created objects 23 are known (Structure for StringObject etc.). So we can first query the cached string 24 before actually converting primitives to objects. 25 26 This patch improves wtb-lebab.js by roughly 2%. 27 28 before: lebab: 8.90 runs/s 29 after : lebab: 9.09 runs/s 30 31 * JavaScriptCore.xcodeproj/project.pbxproj: 32 * dfg/DFGAbstractInterpreterInlines.h: 33 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 34 * dfg/DFGByteCodeParser.cpp: 35 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 36 * dfg/DFGClobberize.h: 37 (JSC::DFG::clobberize): 38 * dfg/DFGDoesGC.cpp: 39 (JSC::DFG::doesGC): 40 * dfg/DFGFixupPhase.cpp: 41 (JSC::DFG::FixupPhase::fixupNode): 42 (JSC::DFG::FixupPhase::fixupObjectToString): 43 * dfg/DFGNodeType.h: 44 * dfg/DFGOperations.cpp: 45 * dfg/DFGOperations.h: 46 * dfg/DFGPredictionPropagationPhase.cpp: 47 * dfg/DFGSafeToExecute.h: 48 (JSC::DFG::safeToExecute): 49 * dfg/DFGSpeculativeJIT.cpp: 50 (JSC::DFG::SpeculativeJIT::compileObjectToString): 51 * dfg/DFGSpeculativeJIT.h: 52 * dfg/DFGSpeculativeJIT32_64.cpp: 53 (JSC::DFG::SpeculativeJIT::compile): 54 * dfg/DFGSpeculativeJIT64.cpp: 55 (JSC::DFG::SpeculativeJIT::compile): 56 * ftl/FTLAbstractHeapRepository.h: 57 * ftl/FTLCapabilities.cpp: 58 (JSC::FTL::canCompile): 59 * ftl/FTLLowerDFGToB3.cpp: 60 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 61 (JSC::FTL::DFG::LowerDFGToB3::compileObjectToString): 62 * runtime/Intrinsic.cpp: 63 (JSC::intrinsicName): 64 * runtime/Intrinsic.h: 65 * runtime/ObjectPrototype.cpp: 66 (JSC::ObjectPrototype::finishCreation): 67 (JSC::objectProtoFuncToString): 68 * runtime/ObjectPrototype.h: 69 * runtime/ObjectPrototypeInlines.h: Added. 70 (JSC::structureForPrimitiveValue): 71 (JSC::objectToString): 72 * runtime/StructureRareData.h: 73 1 74 2019-01-03 Michael Saboff <msaboff@apple.com> 2 75 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r238756 r239612 1625 1625 BC18C4450E16F5CD00B34460 /* ObjectConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C70E16D4E900A06E92 /* ObjectConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1626 1626 BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1627 5E158AC350BC4EC7877DC0F4 /* ObjectPrototypeInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D0CC9E1CBC149AB8F403434 /* ObjectPrototypeInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1627 1628 BC18C4480E16F5CD00B34460 /* Operations.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8780255597D01FF60F7 /* Operations.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1628 1629 BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F0B3AA09BB4DC00068FCE3 /* Parser.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 4487 4488 BC2680C80E16D4E900A06E92 /* ObjectPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectPrototype.cpp; sourceTree = "<group>"; }; 4488 4489 BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectPrototype.h; sourceTree = "<group>"; }; 4490 6D0CC9E1CBC149AB8F403434 /* ObjectPrototypeInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectPrototypeInlines.h; sourceTree = "<group>"; }; 4489 4491 BC2680E60E16D52300A06E92 /* NumberConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumberConstructor.lut.h; sourceTree = "<group>"; }; 4490 4492 BC3046060E1F497F003232CF /* Error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Error.h; sourceTree = "<group>"; }; … … 7001 7003 BC2680C80E16D4E900A06E92 /* ObjectPrototype.cpp */, 7002 7004 BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */, 7005 6D0CC9E1CBC149AB8F403434 /* ObjectPrototypeInlines.h */, 7003 7006 F692A8770255597D01FF60F7 /* Operations.cpp */, 7004 7007 F692A8780255597D01FF60F7 /* Operations.h */, … … 9448 9451 0FD3E40C1B618B6600C80E1E /* ObjectPropertyConditionSet.h in Headers */, 9449 9452 BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */, 9453 5E158AC350BC4EC7877DC0F4 /* ObjectPrototypeInlines.h in Headers */, 9450 9454 E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */, 9451 9455 14F79F70216EAFD200046D39 /* Opcode.h in Headers */, -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r239438 r239612 2618 2618 clobberWorld(); 2619 2619 setTypeForNode(node, SpecArray); 2620 break; 2621 } 2622 2623 case ObjectToString: { 2624 AbstractValue& source = forNode(node->child1()); 2625 bool clobbering = node->child1().useKind() != OtherUse; 2626 if (JSValue sourceValue = source.m_value) { 2627 if (sourceValue.isUndefinedOrNull()) { 2628 if (clobbering) 2629 didFoldClobberWorld(); 2630 setConstant(node, *m_graph.freeze(sourceValue.isUndefined() ? m_vm.smallStrings.undefinedObjectString() : m_vm.smallStrings.nullObjectString())); 2631 break; 2632 } 2633 } 2634 2635 if (clobbering) 2636 clobberWorld(); 2637 setTypeForNode(node, SpecString); 2620 2638 break; 2621 2639 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r239324 r239612 2699 2699 insertChecks(); 2700 2700 set(result, addToGraph(ObjectKeys, get(virtualRegisterForArgument(1, registerOffset)))); 2701 return true; 2702 } 2703 2704 case ObjectPrototypeToStringIntrinsic: { 2705 insertChecks(); 2706 Node* value = get(virtualRegisterForArgument(0, registerOffset)); 2707 set(result, addToGraph(ObjectToString, value)); 2701 2708 return true; 2702 2709 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r239438 r239612 682 682 return; 683 683 684 case ObjectToString: 685 switch (node->child1().useKind()) { 686 case OtherUse: 687 def(PureValue(node)); 688 return; 689 case UntypedUse: 690 read(World); 691 write(Heap); 692 return; 693 default: 694 RELEASE_ASSERT_NOT_REACHED(); 695 return; 696 } 697 684 698 case AtomicsAdd: 685 699 case AtomicsAnd: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r239324 r239612 373 373 case StringSlice: 374 374 case StringValueOf: 375 case ObjectToString: 375 376 case CreateRest: 376 377 case ToLowerCase: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r239324 r239612 2145 2145 case StringValueOf: { 2146 2146 fixupStringValueOf(node); 2147 break; 2148 } 2149 2150 case ObjectToString: { 2151 fixupObjectToString(node); 2147 2152 break; 2148 2153 } … … 2932 2937 } 2933 2938 2939 void fixupObjectToString(Node* node) 2940 { 2941 if (node->child1()->shouldSpeculateOther()) { 2942 fixEdge<OtherUse>(node->child1()); 2943 node->clearFlags(NodeMustGenerate); 2944 return; 2945 } 2946 } 2947 2934 2948 bool attemptToMakeFastStringAdd(Node* node) 2935 2949 { -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r239324 r239612 267 267 macro(ObjectCreate, NodeMustGenerate | NodeResultJS) \ 268 268 macro(ObjectKeys, NodeMustGenerate | NodeResultJS) \ 269 macro(ObjectToString, NodeMustGenerate | NodeResultJS) \ 269 270 \ 270 271 /* Atomics object functions. */\ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r239427 r239612 64 64 #include "NumberConstructor.h" 65 65 #include "ObjectConstructor.h" 66 #include "ObjectPrototypeInlines.h" 66 67 #include "Operations.h" 67 68 #include "ParseInt.h" … … 72 73 #include "ScopedArguments.h" 73 74 #include "StringConstructor.h" 75 #include "StructureRareDataInlines.h" 74 76 #include "SuperSampler.h" 75 77 #include "Symbol.h" … … 2153 2155 throwVMTypeError(exec, scope); 2154 2156 return nullptr; 2157 } 2158 2159 JSString* JIT_OPERATION operationObjectToString(ExecState* exec, EncodedJSValue source) 2160 { 2161 VM& vm = exec->vm(); 2162 NativeCallFrameTracer tracer(&vm, exec); 2163 return objectToString(exec, JSValue::decode(source)); 2155 2164 } 2156 2165 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r239324 r239612 206 206 JSString* JIT_OPERATION operationStringValueOf(ExecState*, EncodedJSValue); 207 207 JSString* JIT_OPERATION operationToLowerCase(ExecState*, JSString*, uint32_t); 208 JSString* JIT_OPERATION operationObjectToString(ExecState*, EncodedJSValue); 208 209 209 210 char* JIT_OPERATION operationInt32ToString(ExecState*, int32_t, int32_t); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r239324 r239612 885 885 case StringSlice: 886 886 case ToLowerCase: 887 case ObjectToString: 887 888 setPrediction(SpecString); 888 889 break; -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r239324 r239612 453 453 case StringSlice: 454 454 case ToLowerCase: 455 case ObjectToString: 455 456 case GetMapBucket: 456 457 case GetMapBucketHead: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r239427 r239612 12454 12454 } 12455 12455 12456 void SpeculativeJIT::compileObjectToString(Node* node) 12457 { 12458 switch (node->child1().useKind()) { 12459 case OtherUse: { 12460 JSValueOperand source(this, node->child1(), ManualOperandSpeculation); 12461 GPRTemporary result(this); 12462 12463 JSValueRegs sourceRegs = source.jsValueRegs(); 12464 GPRReg resultGPR = result.gpr(); 12465 12466 speculateOther(node->child1(), sourceRegs); 12467 12468 auto isUndefined = m_jit.branchIfUndefined(sourceRegs); 12469 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->smallStrings.nullObjectString()), resultGPR); 12470 auto done = m_jit.jump(); 12471 isUndefined.link(&m_jit); 12472 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->smallStrings.undefinedObjectString()), resultGPR); 12473 done.link(&m_jit); 12474 12475 cellResult(resultGPR, node); 12476 return; 12477 } 12478 case UntypedUse: { 12479 JSValueOperand source(this, node->child1()); 12480 12481 JSValueRegs sourceRegs = source.jsValueRegs(); 12482 12483 GPRTemporary structure(this); 12484 GPRTemporary scratch(this); 12485 12486 GPRReg structureGPR = structure.gpr(); 12487 GPRReg scratchGPR = scratch.gpr(); 12488 12489 CCallHelpers::JumpList slowCases; 12490 slowCases.append(m_jit.branchIfNotCell(sourceRegs)); 12491 slowCases.append(m_jit.branchIfNotObject(sourceRegs.payloadGPR())); 12492 12493 m_jit.emitLoadStructure(*m_jit.vm(), sourceRegs.payloadGPR(), structureGPR, scratchGPR); 12494 m_jit.loadPtr(CCallHelpers::Address(structureGPR, Structure::previousOrRareDataOffset()), scratchGPR); 12495 12496 slowCases.append(m_jit.branchTestPtr(CCallHelpers::Zero, scratchGPR)); 12497 slowCases.append(m_jit.branch32(CCallHelpers::Equal, CCallHelpers::Address(scratchGPR, JSCell::structureIDOffset()), TrustedImm32(bitwise_cast<int32_t>(m_jit.vm()->structureStructure->structureID())))); 12498 12499 m_jit.loadPtr(CCallHelpers::Address(scratchGPR, StructureRareData::offsetOfObjectToStringValue()), scratchGPR); 12500 slowCases.append(m_jit.branchTestPtr(CCallHelpers::Zero, scratchGPR)); 12501 12502 addSlowPathGenerator(slowPathCall(slowCases, this, operationObjectToString, scratchGPR, sourceRegs)); 12503 12504 cellResult(scratchGPR, node); 12505 return; 12506 } 12507 default: 12508 DFG_CRASH(m_graph, node, "Bad use kind"); 12509 return; 12510 } 12511 } 12512 12456 12513 void SpeculativeJIT::compileObjectCreate(Node* node) 12457 12514 { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r239427 r239612 1481 1481 void compileToThis(Node*); 1482 1482 void compileObjectKeys(Node*); 1483 void compileObjectToString(Node*); 1483 1484 void compileObjectCreate(Node*); 1484 1485 void compileCreateThis(Node*); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r239427 r239612 3104 3104 case StringValueOf: { 3105 3105 compileToStringOrCallStringConstructorOrStringValueOf(node); 3106 break; 3107 } 3108 3109 case ObjectToString: { 3110 compileObjectToString(node); 3106 3111 break; 3107 3112 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r239427 r239612 3346 3346 case StringValueOf: { 3347 3347 compileToStringOrCallStringConstructorOrStringValueOf(node); 3348 break; 3349 } 3350 3351 case ObjectToString: { 3352 compileObjectToString(node); 3348 3353 break; 3349 3354 } -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
r239324 r239612 121 121 macro(Structure_structureID, Structure::structureIDOffset()) \ 122 122 macro(StructureRareData_cachedOwnKeys, StructureRareData::offsetOfCachedOwnKeys()) \ 123 macro(StructureRareData_objectToStringValue, StructureRareData::offsetOfObjectToStringValue()) \ 123 124 macro(HashMapImpl_capacity, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()) \ 124 125 macro(HashMapImpl_buffer, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()) \ -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r239324 r239612 334 334 case StringSlice: 335 335 case ToLowerCase: 336 case ObjectToString: 336 337 case NumberToStringWithRadix: 337 338 case NumberToStringWithValidRadixConstant: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r239427 r239612 938 938 compileStringFromCharCode(); 939 939 break; 940 case ObjectToString: 941 compileObjectToString(); 942 break; 940 943 case GetByOffset: 941 944 case GetGetterSetterByOffset: … … 6418 6421 DFG_CRASH(m_graph, m_node, "Bad use kind"); 6419 6422 break; 6423 } 6424 } 6425 6426 void compileObjectToString() 6427 { 6428 switch (m_node->child1().useKind()) { 6429 case OtherUse: { 6430 speculate(m_node->child1()); 6431 LValue source = lowJSValue(m_node->child1(), ManualOperandSpeculation); 6432 LValue result = m_out.select(m_out.equal(source, m_out.constInt64(ValueUndefined)), 6433 weakPointer(vm().smallStrings.undefinedObjectString()), weakPointer(vm().smallStrings.nullObjectString())); 6434 setJSValue(result); 6435 return; 6436 } 6437 case UntypedUse: { 6438 LBasicBlock cellCase = m_out.newBlock(); 6439 LBasicBlock objectCase = m_out.newBlock(); 6440 LBasicBlock notNullCase = m_out.newBlock(); 6441 LBasicBlock rareDataCase = m_out.newBlock(); 6442 LBasicBlock slowCase = m_out.newBlock(); 6443 LBasicBlock continuation = m_out.newBlock(); 6444 6445 LValue source = lowJSValue(m_node->child1()); 6446 m_out.branch(isCell(source, provenType(m_node->child1())), unsure(cellCase), unsure(slowCase)); 6447 6448 LBasicBlock lastNext = m_out.appendTo(cellCase, objectCase); 6449 m_out.branch(isObject(source, provenType(m_node->child1()) & SpecCell), unsure(objectCase), unsure(slowCase)); 6450 6451 m_out.appendTo(objectCase, notNullCase); 6452 LValue structure = loadStructure(source); 6453 LValue previousOrRareData = m_out.loadPtr(structure, m_heaps.Structure_previousOrRareData); 6454 m_out.branch(m_out.notNull(previousOrRareData), unsure(notNullCase), unsure(slowCase)); 6455 6456 m_out.appendTo(notNullCase, rareDataCase); 6457 m_out.branch( 6458 m_out.notEqual(m_out.load32(previousOrRareData, m_heaps.JSCell_structureID), m_out.constInt32(m_graph.m_vm.structureStructure->structureID())), 6459 unsure(rareDataCase), unsure(slowCase)); 6460 6461 m_out.appendTo(rareDataCase, slowCase); 6462 LValue objectToStringValue = m_out.loadPtr(previousOrRareData, m_heaps.StructureRareData_objectToStringValue); 6463 ValueFromBlock fastResult = m_out.anchor(objectToStringValue); 6464 m_out.branch(m_out.isNull(objectToStringValue), unsure(slowCase), unsure(continuation)); 6465 6466 m_out.appendTo(slowCase, continuation); 6467 LValue slowResultValue = vmCall(pointerType(), m_out.operation(operationObjectToString), m_callFrame, source); 6468 ValueFromBlock slowResult = m_out.anchor(slowResultValue); 6469 m_out.jump(continuation); 6470 6471 m_out.appendTo(continuation, lastNext); 6472 setJSValue(m_out.phi(pointerType(), fastResult, slowResult)); 6473 return; 6474 } 6475 default: 6476 DFG_CRASH(m_graph, m_node, "Bad use kind"); 6477 return; 6420 6478 } 6421 6479 } -
trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp
r239324 r239612 122 122 case ObjectKeysIntrinsic: 123 123 return "ObjectKeysIntrinsic"; 124 case ObjectPrototypeToStringIntrinsic: 125 return "ObjectPrototypeToStringIntrinsic"; 124 126 case ReflectGetPrototypeOfIntrinsic: 125 127 return "ReflectGetPrototypeOfIntrinsic"; -
trunk/Source/JavaScriptCore/runtime/Intrinsic.h
r239324 r239612 74 74 ObjectIsIntrinsic, 75 75 ObjectKeysIntrinsic, 76 ObjectPrototypeToStringIntrinsic, 76 77 ReflectGetPrototypeOfIntrinsic, 77 78 StringPrototypeValueOfIntrinsic, -
trunk/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
r239427 r239612 28 28 #include "JSString.h" 29 29 #include "JSCInlines.h" 30 #include "ObjectPrototypeInlines.h" 30 31 #include "PropertySlot.h" 31 32 #include "StructureInlines.h" … … 43 44 static EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*); 44 45 static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*); 46 static EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*); 45 47 46 48 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ObjectPrototype); … … 59 61 didBecomePrototype(); 60 62 61 JSC_NATIVE_ FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, objectProtoFuncToString, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);63 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, objectProtoFuncToString, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, ObjectPrototypeToStringIntrinsic); 62 64 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toLocaleString, objectProtoFuncToLocaleString, static_cast<unsigned>(PropertyAttribute::DontEnum), 0); 63 65 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->valueOf, objectProtoFuncValueOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 0); … … 312 314 EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec) 313 315 { 314 VM& vm = exec->vm();315 auto scope = DECLARE_THROW_SCOPE(vm);316 317 316 JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); 318 if (thisValue.isUndefinedOrNull()) 319 return JSValue::encode(thisValue.isUndefined() ? vm.smallStrings.undefinedObjectString() : vm.smallStrings.nullObjectString()); 320 JSObject* thisObject = thisValue.toObject(exec); 321 EXCEPTION_ASSERT(!!scope.exception() == !thisObject); 322 if (!thisObject) 323 return JSValue::encode(jsUndefined()); 324 325 auto result = thisObject->structure(vm)->objectToStringValue(); 326 if (result) 327 return JSValue::encode(result); 328 329 PropertyName toStringTagSymbol = vm.propertyNames->toStringTagSymbol; 330 RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->getPropertySlot(exec, toStringTagSymbol, [&] (bool found, PropertySlot& toStringTagSlot) -> JSValue { 331 if (found) { 332 JSValue stringTag = toStringTagSlot.getValue(exec, toStringTagSymbol); 333 RETURN_IF_EXCEPTION(scope, { }); 334 if (stringTag.isString()) { 335 JSRopeString::RopeBuilder<RecordOverflow> ropeBuilder(vm); 336 ropeBuilder.append(vm.smallStrings.objectStringStart()); 337 ropeBuilder.append(asString(stringTag)); 338 ropeBuilder.append(vm.smallStrings.singleCharacterString(']')); 339 if (ropeBuilder.hasOverflowed()) 340 return throwOutOfMemoryError(exec, scope); 341 342 JSString* result = ropeBuilder.release(); 343 thisObject->structure(vm)->setObjectToStringValue(exec, vm, result, toStringTagSlot); 344 return result; 345 } 346 } 347 348 String tag = thisObject->methodTable(vm)->toStringName(thisObject, exec); 349 RETURN_IF_EXCEPTION(scope, { }); 350 String newString = tryMakeString("[object ", WTFMove(tag), "]"); 351 if (!newString) 352 return throwOutOfMemoryError(exec, scope); 353 354 auto result = jsNontrivialString(&vm, newString); 355 thisObject->structure(vm)->setObjectToStringValue(exec, vm, result, toStringTagSlot); 356 return result; 357 }))); 317 return JSValue::encode(objectToString(exec, thisValue)); 358 318 } 359 319 -
trunk/Source/JavaScriptCore/runtime/ObjectPrototype.h
r229413 r239612 46 46 }; 47 47 48 JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*);49 50 48 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/StructureRareData.h
r239324 r239612 82 82 bool hasSharedPolyProtoWatchpoint() const { return static_cast<bool>(m_polyProtoWatchpoint); } 83 83 84 static ptrdiff_t offsetOfObjectToStringValue() 85 { 86 return OBJECT_OFFSETOF(StructureRareData, m_objectToStringValue); 87 } 88 84 89 static JSImmutableButterfly* cachedOwnKeysSentinel() { return bitwise_cast<JSImmutableButterfly*>(static_cast<uintptr_t>(1)); } 85 90
Note: See TracChangeset
for help on using the changeset viewer.