Changeset 191215 in webkit
- Timestamp:
- Oct 16, 2015, 3:18:42 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 35 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r191211 r191215 1 2015-10-16 Keith Miller <[email protected]> 2 3 Add Intrinsic Getters and use them to fix performance on the getters of TypedArray properties. 4 https://bugs.webkit.org/show_bug.cgi?id=149687 5 6 Reviewed by Geoffrey Garen. 7 8 Fix test since typedarrays no longer have length as a own property. 9 10 * js/dom/getOwnPropertyDescriptor-expected.txt: 11 * js/resources/getOwnPropertyDescriptor.js: 12 1 13 2015-10-16 Brent Fulgham <[email protected]> 2 14 -
trunk/LayoutTests/js/dom/getOwnPropertyDescriptor-expected.txt
r185370 r191215 158 158 PASS Object.getOwnPropertyDescriptor(document.getElementsByClassName('pass'), 'length').enumerable is true 159 159 PASS Object.getOwnPropertyDescriptor(document.getElementsByClassName('pass'), 'length').configurable is false 160 PASS Object.getOwnPropertyDescriptor(canvasPixelArray, 'length').value is canvasPixelArray.length161 PASS Object.getOwnPropertyDescriptor(canvasPixelArray, 'length').hasOwnProperty('get') is false162 PASS Object.getOwnPropertyDescriptor(canvasPixelArray, 'length').hasOwnProperty('set') is false163 PASS Object.getOwnPropertyDescriptor(canvasPixelArray, 'length').enumerable is true164 PASS Object.getOwnPropertyDescriptor(canvasPixelArray, 'length').configurable is false165 160 PASS Object.getOwnPropertyDescriptor(canvasPixelArray, 0).value is canvasPixelArray[0] 166 161 PASS Object.getOwnPropertyDescriptor(canvasPixelArray, 0).hasOwnProperty('get') is false -
trunk/LayoutTests/js/resources/getOwnPropertyDescriptor.js
r185370 r191215 52 52 var canvas = document.createElement("canvas"); 53 53 var canvasPixelArray = canvas.getContext("2d").createImageData(10,10).data; 54 descriptorShouldBe("canvasPixelArray", "'length'", {writable: false, enumerable: true, configurable: false, value:"canvasPixelArray.length"});55 54 descriptorShouldBe("canvasPixelArray", "0", {writable: true, enumerable: true, configurable: false, value:"canvasPixelArray[0]"}); 56 55 var select = document.createElement("select"); -
trunk/Source/JavaScriptCore/CMakeLists.txt
r191191 r191215 374 374 jit/GCAwareJITStubRoutine.cpp 375 375 jit/HostCallReturnValue.cpp 376 jit/IntrinsicEmitter.cpp 376 377 jit/JIT.cpp 377 378 jit/JITArithmetic.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r191212 r191215 1 2015-10-16 Keith Miller <[email protected]> 2 3 Add Intrinsic Getters and use them to fix performance on the getters of TypedArray properties. 4 https://bugs.webkit.org/show_bug.cgi?id=149687 5 6 Reviewed by Geoffrey Garen. 7 8 Add the ability to create intrinsic getters in both the inline cache and the DFG/FTL. When the 9 getter fetched by a GetById has an intrinsic we know about we add a new intrinsic access case. 10 Once we get to the DFG, we observe that the access case was an intrinsic and add an appropriate 11 GetByIdVariant. We then parse the intrinsic into an appropriate DFG node. 12 13 The first intrinsics are the new TypedArray prototype getters length, byteLength, and byteOffset. 14 15 * CMakeLists.txt: 16 * JavaScriptCore.xcodeproj/project.pbxproj: 17 * bytecode/GetByIdStatus.cpp: 18 (JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback): 19 (JSC::GetByIdStatus::computeFor): 20 * bytecode/GetByIdVariant.cpp: 21 (JSC::GetByIdVariant::GetByIdVariant): 22 (JSC::GetByIdVariant::operator=): 23 (JSC::GetByIdVariant::canMergeIntrinsicStructures): 24 (JSC::GetByIdVariant::attemptToMerge): 25 (JSC::GetByIdVariant::dumpInContext): 26 * bytecode/GetByIdVariant.h: 27 (JSC::GetByIdVariant::intrinsicFunction): 28 (JSC::GetByIdVariant::intrinsic): 29 (JSC::GetByIdVariant::callLinkStatus): Deleted. 30 * bytecode/PolymorphicAccess.cpp: 31 (JSC::AccessGenerationState::addWatchpoint): 32 (JSC::AccessGenerationState::restoreScratch): 33 (JSC::AccessGenerationState::succeed): 34 (JSC::AccessGenerationState::calculateLiveRegistersForCallAndExceptionHandling): 35 (JSC::AccessGenerationState::preserveLiveRegistersToStackForCall): 36 (JSC::AccessGenerationState::restoreLiveRegistersFromStackForCall): 37 (JSC::AccessGenerationState::restoreLiveRegistersFromStackForCallWithThrownException): 38 (JSC::AccessGenerationState::callSiteIndexForExceptionHandlingOrOriginal): 39 (JSC::AccessGenerationState::originalExceptionHandler): 40 (JSC::AccessGenerationState::originalCallSiteIndex): 41 (JSC::AccessCase::getIntrinsic): 42 (JSC::AccessCase::clone): 43 (JSC::AccessCase::visitWeak): 44 (JSC::AccessCase::generate): 45 (WTF::printInternal): 46 (JSC::AccessCase::AccessCase): Deleted. 47 (JSC::AccessCase::get): Deleted. 48 (JSC::AccessCase::replace): Deleted. 49 (JSC::AccessCase::transition): Deleted. 50 * bytecode/PolymorphicAccess.h: 51 (JSC::AccessCase::isGet): 52 (JSC::AccessCase::isPut): 53 (JSC::AccessCase::isIn): 54 (JSC::AccessCase::intrinsicFunction): 55 (JSC::AccessCase::intrinsic): 56 (JSC::AccessGenerationState::AccessGenerationState): 57 (JSC::AccessGenerationState::liveRegistersForCall): 58 (JSC::AccessGenerationState::callSiteIndexForExceptionHandling): 59 (JSC::AccessGenerationState::numberOfStackBytesUsedForRegisterPreservation): 60 (JSC::AccessGenerationState::needsToRestoreRegistersIfException): 61 (JSC::AccessGenerationState::liveRegistersToPreserveAtExceptionHandlingCallSite): 62 * bytecode/PutByIdVariant.h: 63 (JSC::PutByIdVariant::intrinsic): 64 * dfg/DFGAbstractInterpreterInlines.h: 65 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 66 * dfg/DFGArrayMode.cpp: 67 (JSC::DFG::ArrayMode::alreadyChecked): 68 (JSC::DFG::arrayTypeToString): 69 (JSC::DFG::toTypedArrayType): 70 (JSC::DFG::refineTypedArrayType): 71 (JSC::DFG::permitsBoundsCheckLowering): 72 * dfg/DFGArrayMode.h: 73 (JSC::DFG::ArrayMode::supportsLength): 74 (JSC::DFG::ArrayMode::isSomeTypedArrayView): 75 * dfg/DFGByteCodeParser.cpp: 76 (JSC::DFG::ByteCodeParser::attemptToInlineCall): 77 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 78 (JSC::DFG::ByteCodeParser::handleIntrinsicGetter): 79 (JSC::DFG::ByteCodeParser::load): 80 (JSC::DFG::ByteCodeParser::handleGetById): 81 (JSC::DFG::ByteCodeParser::presenceLike): Deleted. 82 (JSC::DFG::ByteCodeParser::store): Deleted. 83 * dfg/DFGClobberize.h: 84 (JSC::DFG::clobberize): 85 * dfg/DFGFixupPhase.cpp: 86 (JSC::DFG::FixupPhase::fixupNode): 87 (JSC::DFG::FixupPhase::convertToGetArrayLength): Deleted. 88 (JSC::DFG::FixupPhase::prependGetArrayLength): Deleted. 89 (JSC::DFG::FixupPhase::fixupChecksInBlock): Deleted. 90 * dfg/DFGGraph.cpp: 91 (JSC::DFG::Graph::tryGetFoldableView): 92 * dfg/DFGPredictionPropagationPhase.cpp: 93 (JSC::DFG::PredictionPropagationPhase::propagate): 94 * dfg/DFGSpeculativeJIT.cpp: 95 (JSC::DFG::SpeculativeJIT::checkArray): 96 (JSC::DFG::SpeculativeJIT::compileGetArrayLength): 97 * ftl/FTLCapabilities.cpp: 98 (JSC::FTL::canCompile): 99 * ftl/FTLLowerDFGToLLVM.cpp: 100 (JSC::FTL::DFG::LowerDFGToLLVM::compileGetArrayLength): 101 * jit/IntrinsicEmitter.cpp: Added. 102 (JSC::AccessCase::canEmitIntrinsicGetter): 103 (JSC::AccessCase::emitIntrinsicGetter): 104 * jit/Repatch.cpp: 105 (JSC::tryCacheGetByID): 106 * runtime/Intrinsic.h: 107 * runtime/JSArrayBufferView.cpp: 108 (JSC::JSArrayBufferView::put): 109 (JSC::JSArrayBufferView::defineOwnProperty): 110 (JSC::JSArrayBufferView::deleteProperty): 111 (JSC::JSArrayBufferView::getOwnNonIndexPropertyNames): 112 (JSC::JSArrayBufferView::getOwnPropertySlot): Deleted. 113 (JSC::JSArrayBufferView::finalize): Deleted. 114 * runtime/JSDataView.cpp: 115 (JSC::JSDataView::getOwnPropertySlot): 116 (JSC::JSDataView::put): 117 (JSC::JSDataView::defineOwnProperty): 118 (JSC::JSDataView::deleteProperty): 119 (JSC::JSDataView::getOwnNonIndexPropertyNames): 120 * runtime/JSDataView.h: 121 * runtime/JSFunction.h: 122 * runtime/JSFunctionInlines.h: 123 (JSC::JSFunction::intrinsic): 124 * runtime/JSGenericTypedArrayView.h: 125 * runtime/JSGenericTypedArrayViewInlines.h: 126 (JSC::JSGenericTypedArrayView<Adaptor>::getOwnPropertySlot): 127 (JSC::JSGenericTypedArrayView<Adaptor>::defineOwnProperty): 128 (JSC::JSGenericTypedArrayView<Adaptor>::deleteProperty): 129 (JSC::JSGenericTypedArrayView<Adaptor>::getOwnPropertySlotByIndex): Deleted. 130 (JSC::JSGenericTypedArrayView<Adaptor>::visitChildren): Deleted. 131 * runtime/JSObject.cpp: 132 (JSC::JSObject::putDirectNativeIntrinsicGetter): 133 * runtime/JSObject.h: 134 * runtime/JSTypedArrayViewPrototype.cpp: 135 (JSC::JSTypedArrayViewPrototype::finishCreation): 136 * tests/stress/typedarray-add-property-to-base-object.js: Added. 137 (body.foo): 138 (body): 139 * tests/stress/typedarray-bad-getter.js: Added. 140 (body.foo): 141 (body.get Bar): 142 (body): 143 * tests/stress/typedarray-getter-on-self.js: Added. 144 (body.foo): 145 (body.bar): 146 (body.baz): 147 (body.get for): 148 (body): 149 * tests/stress/typedarray-intrinsic-getters-change-prototype.js: Added. 150 (body.foo): 151 (body.bar): 152 (body.baz): 153 (body): 154 1 155 2015-10-16 Keith Miller <[email protected]> 2 156 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r191191 r191215 1725 1725 C4F4B6F61A05C984005CAB76 /* objc_generator_templates.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D81A05C76F005CAB76 /* objc_generator_templates.py */; settings = {ATTRIBUTES = (Private, ); }; }; 1726 1726 DC00039319D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h in Headers */ = {isa = PBXBuildFile; fileRef = DC00039019D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h */; }; 1727 DE5A0A001BA3AC3E003D4424 /* IntrinsicEmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */; }; 1727 1728 DEA7E2441BBC677200D78440 /* JSTypedArrayViewPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */; }; 1728 1729 DEA7E2451BBC677F00D78440 /* JSTypedArrayViewPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3618 3619 D21202290AD4310C00ED79B6 /* DateConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateConversion.h; sourceTree = "<group>"; }; 3619 3620 DC00039019D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPreciseLocalClobberize.h; path = dfg/DFGPreciseLocalClobberize.h; sourceTree = "<group>"; }; 3621 DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntrinsicEmitter.cpp; sourceTree = "<group>"; }; 3620 3622 E124A8F50E555775003091F1 /* OpaqueJSString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueJSString.h; sourceTree = "<group>"; }; 3621 3623 E124A8F60E555775003091F1 /* OpaqueJSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpaqueJSString.cpp; sourceTree = "<group>"; }; … … 4172 4174 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */, 4173 4175 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */, 4176 DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */, 4174 4177 1429D92D0ED22D7000B89619 /* JIT.cpp */, 4175 4178 1429D92E0ED22D7000B89619 /* JIT.h */, … … 7507 7510 0F8F9446166764F100D61971 /* CodeOrigin.cpp in Sources */, 7508 7511 86B5826714D2796C00A9C306 /* CodeProfile.cpp in Sources */, 7512 DE5A0A001BA3AC3E003D4424 /* IntrinsicEmitter.cpp in Sources */, 7509 7513 86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */, 7510 7514 0F8F943C1667631300D61971 /* CodeSpecializationKind.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
r190561 r191215 208 208 case ComplexGetStatus::Inlineable: { 209 209 std::unique_ptr<CallLinkStatus> callLinkStatus; 210 JSFunction* intrinsicFunction = nullptr; 211 210 212 switch (access.type()) { 211 213 case AccessCase::Load: { 214 break; 215 } 216 case AccessCase::IntrinsicGetter: { 217 intrinsicFunction = access.intrinsicFunction(); 212 218 break; 213 219 } … … 228 234 GetByIdVariant variant( 229 235 StructureSet(structure), complexGetStatus.offset(), 230 complexGetStatus.conditionSet(), WTF::move(callLinkStatus)); 231 236 complexGetStatus.conditionSet(), WTF::move(callLinkStatus), 237 intrinsicFunction); 238 232 239 if (!result.appendVariant(variant)) 233 240 return GetByIdStatus(slowPathState, true); … … 315 322 return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it. 316 323 if (attributes & Accessor) 317 return GetByIdStatus(MakesCalls); // We could be smarter here, like streng ht-reducing this to a Call.324 return GetByIdStatus(MakesCalls); // We could be smarter here, like strength-reducing this to a Call. 318 325 319 326 if (!result.appendVariant(GetByIdVariant(structure, offset))) -
trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
r187780 r191215 36 36 const StructureSet& structureSet, PropertyOffset offset, 37 37 const ObjectPropertyConditionSet& conditionSet, 38 std::unique_ptr<CallLinkStatus> callLinkStatus) 38 std::unique_ptr<CallLinkStatus> callLinkStatus, 39 JSFunction* intrinsicFunction) 39 40 : m_structureSet(structureSet) 40 41 , m_conditionSet(conditionSet) 41 42 , m_offset(offset) 42 43 , m_callLinkStatus(WTF::move(callLinkStatus)) 44 , m_intrinsicFunction(intrinsicFunction) 43 45 { 44 46 if (!structureSet.size()) { … … 46 48 ASSERT(conditionSet.isEmpty()); 47 49 } 50 if (intrinsicFunction) 51 ASSERT(intrinsic() != NoIntrinsic); 48 52 } 49 53 … … 61 65 m_conditionSet = other.m_conditionSet; 62 66 m_offset = other.m_offset; 67 m_intrinsicFunction = other.m_intrinsicFunction; 63 68 if (other.m_callLinkStatus) 64 69 m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus); … … 68 73 } 69 74 75 inline bool GetByIdVariant::canMergeIntrinsicStructures(const GetByIdVariant& other) const 76 { 77 if (m_intrinsicFunction != other.m_intrinsicFunction) 78 return false; 79 switch (intrinsic()) { 80 case TypedArrayByteLengthIntrinsic: { 81 // We can merge these sets as long as the element size of the two sets is the same. 82 TypedArrayType thisType = (*m_structureSet.begin())->classInfo()->typedArrayStorageType; 83 TypedArrayType otherType = (*other.m_structureSet.begin())->classInfo()->typedArrayStorageType; 84 85 ASSERT(isTypedView(thisType) && isTypedView(otherType)); 86 87 return logElementSize(thisType) == logElementSize(otherType); 88 } 89 90 default: 91 return true; 92 } 93 RELEASE_ASSERT_NOT_REACHED(); 94 } 95 70 96 bool GetByIdVariant::attemptToMerge(const GetByIdVariant& other) 71 97 { … … 73 99 return false; 74 100 if (m_callLinkStatus || other.m_callLinkStatus) 101 return false; 102 103 if (!canMergeIntrinsicStructures(other)) 75 104 return false; 76 105 … … 108 137 if (m_callLinkStatus) 109 138 out.print(", call = ", *m_callLinkStatus); 139 if (m_intrinsicFunction) 140 out.print(", intrinsic = ", *m_intrinsicFunction); 110 141 out.print(">"); 111 142 } -
trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h
r187780 r191215 44 44 const StructureSet& structureSet = StructureSet(), PropertyOffset offset = invalidOffset, 45 45 const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(), 46 std::unique_ptr<CallLinkStatus> callLinkStatus = nullptr); 47 46 std::unique_ptr<CallLinkStatus> = nullptr, 47 JSFunction* = nullptr); 48 48 49 ~GetByIdVariant(); 49 50 … … 61 62 PropertyOffset offset() const { return m_offset; } 62 63 CallLinkStatus* callLinkStatus() const { return m_callLinkStatus.get(); } 63 64 JSFunction* intrinsicFunction() const { return m_intrinsicFunction; } 65 Intrinsic intrinsic() const { return m_intrinsicFunction ? m_intrinsicFunction->intrinsic() : NoIntrinsic; } 66 64 67 bool attemptToMerge(const GetByIdVariant& other); 65 68 … … 69 72 private: 70 73 friend class GetByIdStatus; 74 75 bool canMergeIntrinsicStructures(const GetByIdVariant&) const; 71 76 72 77 StructureSet m_structureSet; … … 74 79 PropertyOffset m_offset; 75 80 std::unique_ptr<CallLinkStatus> m_callLinkStatus; 81 JSFunction* m_intrinsicFunction; 76 82 }; 77 83 -
trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp
r191016 r191215 48 48 static const bool verbose = false; 49 49 50 struct AccessGenerationState { 51 AccessGenerationState() 52 : m_calculatedRegistersForCallAndExceptionHandling(false) 53 , m_needsToRestoreRegistersIfException(false) 54 , m_calculatedCallSiteIndex(false) 55 { 56 } 57 CCallHelpers* jit { nullptr }; 58 ScratchRegisterAllocator* allocator; 59 unsigned numberOfBytesUsedToPreserveReusedRegisters { 0 }; 60 PolymorphicAccess* access { nullptr }; 61 StructureStubInfo* stubInfo { nullptr }; 62 CCallHelpers::JumpList success; 63 CCallHelpers::JumpList failAndRepatch; 64 CCallHelpers::JumpList failAndIgnore; 65 GPRReg baseGPR { InvalidGPRReg }; 66 JSValueRegs valueRegs; 67 GPRReg scratchGPR { InvalidGPRReg }; 68 Vector<std::function<void(LinkBuffer&)>> callbacks; 69 const Identifier* ident; 70 std::unique_ptr<WatchpointsOnStructureStubInfo> watchpoints; 71 Vector<WriteBarrier<JSCell>> weakReferences; 72 73 Watchpoint* addWatchpoint(const ObjectPropertyCondition& condition = ObjectPropertyCondition()) 74 { 75 return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint( 76 watchpoints, jit->codeBlock(), stubInfo, condition); 77 } 78 79 void restoreScratch() 80 { 81 allocator->restoreReusedRegistersByPopping(*jit, numberOfBytesUsedToPreserveReusedRegisters); 82 } 83 84 void succeed() 85 { 86 restoreScratch(); 87 success.append(jit->jump()); 88 } 89 90 void calculateLiveRegistersForCallAndExceptionHandling() 91 { 92 if (!m_calculatedRegistersForCallAndExceptionHandling) { 93 m_calculatedRegistersForCallAndExceptionHandling = true; 94 95 m_liveRegistersToPreserveAtExceptionHandlingCallSite = jit->codeBlock()->jitCode()->liveRegistersToPreserveAtExceptionHandlingCallSite(jit->codeBlock(), stubInfo->callSiteIndex); 96 m_needsToRestoreRegistersIfException = m_liveRegistersToPreserveAtExceptionHandlingCallSite.numberOfSetRegisters() > 0; 97 if (m_needsToRestoreRegistersIfException) 98 RELEASE_ASSERT(JITCode::isOptimizingJIT(jit->codeBlock()->jitType())); 99 100 m_liveRegistersForCall = RegisterSet(m_liveRegistersToPreserveAtExceptionHandlingCallSite, allocator->usedRegisters()); 101 m_liveRegistersForCall.exclude(RegisterSet::registersToNotSaveForCall()); 102 } 103 } 104 105 void preserveLiveRegistersToStackForCall() 106 { 107 unsigned extraStackPadding = 0; 108 unsigned numberOfStackBytesUsedForRegisterPreservation = ScratchRegisterAllocator::preserveRegistersToStackForCall(*jit, liveRegistersForCall(), extraStackPadding); 109 if (m_numberOfStackBytesUsedForRegisterPreservation != std::numeric_limits<unsigned>::max()) 110 RELEASE_ASSERT(numberOfStackBytesUsedForRegisterPreservation == m_numberOfStackBytesUsedForRegisterPreservation); 111 m_numberOfStackBytesUsedForRegisterPreservation = numberOfStackBytesUsedForRegisterPreservation; 112 } 113 114 void restoreLiveRegistersFromStackForCall(bool isGetter) 115 { 116 RegisterSet dontRestore; 117 if (isGetter) { 118 // This is the result value. We don't want to overwrite the result with what we stored to the stack. 119 // We sometimes have to store it to the stack just in case we throw an exception and need the original value. 120 dontRestore.set(valueRegs); 121 } 122 restoreLiveRegistersFromStackForCall(dontRestore); 123 } 124 125 void restoreLiveRegistersFromStackForCallWithThrownException() 126 { 127 // Even if we're a getter, we don't want to ignore the result value like we normally do 128 // because the getter threw, and therefore, didn't return a value that means anything. 129 // Instead, we want to restore that register to what it was upon entering the getter 130 // inline cache. The subtlety here is if the base and the result are the same register, 131 // and the getter threw, we want OSR exit to see the original base value, not the result 132 // of the getter call. 133 RegisterSet dontRestore = liveRegistersForCall(); 134 // As an optimization here, we only need to restore what is live for exception handling. 135 // We can construct the dontRestore set to accomplish this goal by having it contain only 136 // what is live for call but not live for exception handling. By ignoring things that are 137 // only live at the call but not the exception handler, we will only restore things live 138 // at the exception handler. 139 dontRestore.exclude(liveRegistersToPreserveAtExceptionHandlingCallSite()); 140 restoreLiveRegistersFromStackForCall(dontRestore); 141 } 142 143 void restoreLiveRegistersFromStackForCall(const RegisterSet& dontRestore) 144 { 145 unsigned extraStackPadding = 0; 146 ScratchRegisterAllocator::restoreRegistersFromStackForCall(*jit, liveRegistersForCall(), dontRestore, m_numberOfStackBytesUsedForRegisterPreservation, extraStackPadding); 147 } 148 149 const RegisterSet& liveRegistersForCall() 150 { 151 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 152 return m_liveRegistersForCall; 153 } 154 155 CallSiteIndex callSiteIndexForExceptionHandlingOrOriginal() 156 { 157 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 158 159 if (!m_calculatedCallSiteIndex) { 160 m_calculatedCallSiteIndex = true; 161 162 if (m_needsToRestoreRegistersIfException) 163 m_callSiteIndex = jit->codeBlock()->newExceptionHandlingCallSiteIndex(stubInfo->callSiteIndex); 164 else 165 m_callSiteIndex = originalCallSiteIndex(); 166 } 167 168 return m_callSiteIndex; 169 } 170 171 CallSiteIndex callSiteIndexForExceptionHandling() 172 { 173 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 174 RELEASE_ASSERT(m_needsToRestoreRegistersIfException); 175 RELEASE_ASSERT(m_calculatedCallSiteIndex); 176 return m_callSiteIndex; 177 } 178 179 const HandlerInfo& originalExceptionHandler() const 180 { 181 RELEASE_ASSERT(m_needsToRestoreRegistersIfException); 182 HandlerInfo* exceptionHandler = jit->codeBlock()->handlerForIndex(stubInfo->callSiteIndex.bits()); 183 RELEASE_ASSERT(exceptionHandler); 184 return *exceptionHandler; 185 } 186 187 unsigned numberOfStackBytesUsedForRegisterPreservation() const 188 { 189 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 190 return m_numberOfStackBytesUsedForRegisterPreservation; 191 } 192 193 bool needsToRestoreRegistersIfException() const { return m_needsToRestoreRegistersIfException; } 194 CallSiteIndex originalCallSiteIndex() const { return stubInfo->callSiteIndex; } 195 196 private: 197 const RegisterSet& liveRegistersToPreserveAtExceptionHandlingCallSite() 198 { 199 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 200 return m_liveRegistersToPreserveAtExceptionHandlingCallSite; 201 } 202 203 RegisterSet m_liveRegistersToPreserveAtExceptionHandlingCallSite; 204 RegisterSet m_liveRegistersForCall; 205 CallSiteIndex m_callSiteIndex { CallSiteIndex(std::numeric_limits<unsigned>::max()) }; 206 unsigned m_numberOfStackBytesUsedForRegisterPreservation { std::numeric_limits<unsigned>::max() }; 207 bool m_calculatedRegistersForCallAndExceptionHandling : 1; 208 bool m_needsToRestoreRegistersIfException : 1; 209 bool m_calculatedCallSiteIndex : 1; 210 }; 50 Watchpoint* AccessGenerationState::addWatchpoint(const ObjectPropertyCondition& condition) 51 { 52 return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint( 53 watchpoints, jit->codeBlock(), stubInfo, condition); 54 } 55 56 void AccessGenerationState::restoreScratch() 57 { 58 allocator->restoreReusedRegistersByPopping(*jit, numberOfBytesUsedToPreserveReusedRegisters); 59 } 60 61 void AccessGenerationState::succeed() 62 { 63 restoreScratch(); 64 success.append(jit->jump()); 65 } 66 67 void AccessGenerationState::calculateLiveRegistersForCallAndExceptionHandling() 68 { 69 if (!m_calculatedRegistersForCallAndExceptionHandling) { 70 m_calculatedRegistersForCallAndExceptionHandling = true; 71 72 m_liveRegistersToPreserveAtExceptionHandlingCallSite = jit->codeBlock()->jitCode()->liveRegistersToPreserveAtExceptionHandlingCallSite(jit->codeBlock(), stubInfo->callSiteIndex); 73 m_needsToRestoreRegistersIfException = m_liveRegistersToPreserveAtExceptionHandlingCallSite.numberOfSetRegisters() > 0; 74 if (m_needsToRestoreRegistersIfException) 75 RELEASE_ASSERT(JITCode::isOptimizingJIT(jit->codeBlock()->jitType())); 76 77 m_liveRegistersForCall = RegisterSet(m_liveRegistersToPreserveAtExceptionHandlingCallSite, allocator->usedRegisters()); 78 m_liveRegistersForCall.exclude(RegisterSet::registersToNotSaveForCall()); 79 } 80 } 81 82 void AccessGenerationState::preserveLiveRegistersToStackForCall() 83 { 84 unsigned extraStackPadding = 0; 85 unsigned numberOfStackBytesUsedForRegisterPreservation = ScratchRegisterAllocator::preserveRegistersToStackForCall(*jit, liveRegistersForCall(), extraStackPadding); 86 if (m_numberOfStackBytesUsedForRegisterPreservation != std::numeric_limits<unsigned>::max()) 87 RELEASE_ASSERT(numberOfStackBytesUsedForRegisterPreservation == m_numberOfStackBytesUsedForRegisterPreservation); 88 m_numberOfStackBytesUsedForRegisterPreservation = numberOfStackBytesUsedForRegisterPreservation; 89 } 90 91 void AccessGenerationState::restoreLiveRegistersFromStackForCall(bool isGetter) 92 { 93 RegisterSet dontRestore; 94 if (isGetter) { 95 // This is the result value. We don't want to overwrite the result with what we stored to the stack. 96 // We sometimes have to store it to the stack just in case we throw an exception and need the original value. 97 dontRestore.set(valueRegs); 98 } 99 restoreLiveRegistersFromStackForCall(dontRestore); 100 } 101 102 void AccessGenerationState::restoreLiveRegistersFromStackForCallWithThrownException() 103 { 104 // Even if we're a getter, we don't want to ignore the result value like we normally do 105 // because the getter threw, and therefore, didn't return a value that means anything. 106 // Instead, we want to restore that register to what it was upon entering the getter 107 // inline cache. The subtlety here is if the base and the result are the same register, 108 // and the getter threw, we want OSR exit to see the original base value, not the result 109 // of the getter call. 110 RegisterSet dontRestore = liveRegistersForCall(); 111 // As an optimization here, we only need to restore what is live for exception handling. 112 // We can construct the dontRestore set to accomplish this goal by having it contain only 113 // what is live for call but not live for exception handling. By ignoring things that are 114 // only live at the call but not the exception handler, we will only restore things live 115 // at the exception handler. 116 dontRestore.exclude(liveRegistersToPreserveAtExceptionHandlingCallSite()); 117 restoreLiveRegistersFromStackForCall(dontRestore); 118 } 119 120 void AccessGenerationState::restoreLiveRegistersFromStackForCall(const RegisterSet& dontRestore) 121 { 122 unsigned extraStackPadding = 0; 123 ScratchRegisterAllocator::restoreRegistersFromStackForCall(*jit, liveRegistersForCall(), dontRestore, m_numberOfStackBytesUsedForRegisterPreservation, extraStackPadding); 124 } 125 126 CallSiteIndex AccessGenerationState::callSiteIndexForExceptionHandlingOrOriginal() 127 { 128 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 129 130 if (!m_calculatedCallSiteIndex) { 131 m_calculatedCallSiteIndex = true; 132 133 if (m_needsToRestoreRegistersIfException) 134 m_callSiteIndex = jit->codeBlock()->newExceptionHandlingCallSiteIndex(stubInfo->callSiteIndex); 135 else 136 m_callSiteIndex = originalCallSiteIndex(); 137 } 138 139 return m_callSiteIndex; 140 } 141 142 const HandlerInfo& AccessGenerationState::originalExceptionHandler() const 143 { 144 RELEASE_ASSERT(m_needsToRestoreRegistersIfException); 145 HandlerInfo* exceptionHandler = jit->codeBlock()->handlerForIndex(stubInfo->callSiteIndex.bits()); 146 RELEASE_ASSERT(exceptionHandler); 147 return *exceptionHandler; 148 } 149 150 CallSiteIndex AccessGenerationState::originalCallSiteIndex() const { return stubInfo->callSiteIndex; } 211 151 212 152 AccessCase::AccessCase() … … 316 256 317 257 result->m_type = type; 258 259 return result; 260 } 261 262 std::unique_ptr<AccessCase> AccessCase::getIntrinsic( 263 VM& vm, JSCell* owner, JSFunction* getter, PropertyOffset offset, 264 Structure* structure, const ObjectPropertyConditionSet& conditionSet) 265 { 266 std::unique_ptr<AccessCase> result(new AccessCase()); 267 268 result->m_type = IntrinsicGetter; 269 result->m_structure.set(vm, owner, structure); 270 result->m_conditionSet = conditionSet; 271 result->m_offset = offset; 272 273 result->m_rareData = std::make_unique<RareData>(); 274 result->m_rareData->intrinsicFunction.set(vm, owner, getter); 318 275 319 276 return result; … … 356 313 result->m_rareData->customAccessor.opaque = rareData->customAccessor.opaque; 357 314 result->m_rareData->customSlotBase = rareData->customSlotBase; 315 result->m_rareData->intrinsicFunction = rareData->intrinsicFunction; 358 316 } 359 317 return result; … … 440 398 m_rareData->callLinkInfo->visitWeak(vm); 441 399 if (m_rareData->customSlotBase && !Heap::isMarked(m_rareData->customSlotBase.get())) 400 return false; 401 if (m_rareData->intrinsicFunction && !Heap::isMarked(m_rareData->intrinsicFunction.get())) 442 402 return false; 443 403 } … … 1107 1067 state.succeed(); 1108 1068 return; 1069 } 1070 1071 case IntrinsicGetter: { 1072 RELEASE_ASSERT(isValidOffset(offset())); 1073 1074 // We need to ensure the getter value does not move from under us. Note that GetterSetters 1075 // are immutable so we just need to watch the property not any value inside it. 1076 Structure* currStructure; 1077 if (m_conditionSet.isEmpty()) 1078 currStructure = structure(); 1079 else 1080 currStructure = m_conditionSet.slotBaseCondition().object()->structure(); 1081 currStructure->startWatchingPropertyForReplacements(vm, offset()); 1082 1083 emitIntrinsicGetter(state); 1084 return; 1109 1085 } } 1110 1086 … … 1442 1418 out.print("CustomSetter"); 1443 1419 return; 1420 case AccessCase::IntrinsicGetter: 1421 out.print("IntrinsicGetter"); 1422 return; 1444 1423 case AccessCase::InHit: 1445 1424 out.print("InHit"); -
trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h
r190735 r191215 30 30 31 31 #include "CodeOrigin.h" 32 #include "JSFunctionInlines.h" 32 33 #include "MacroAssembler.h" 33 34 #include "ObjectPropertyConditionSet.h" … … 42 43 class StructureStubInfo; 43 44 class WatchpointsOnStructureStubInfo; 45 class ScratchRegisterAllocator; 44 46 45 47 struct AccessGenerationState; … … 58 60 CustomGetter, 59 61 CustomSetter, 62 IntrinsicGetter, 60 63 InHit, 61 64 InMiss, … … 78 81 case Getter: 79 82 case CustomGetter: 83 case IntrinsicGetter: 80 84 case ArrayLength: 81 85 case StringLength: … … 91 95 case Getter: 92 96 case CustomGetter: 97 case IntrinsicGetter: 93 98 case InHit: 94 99 case InMiss: … … 111 116 case Getter: 112 117 case CustomGetter: 118 case IntrinsicGetter: 113 119 case Transition: 114 120 case Replace: … … 148 154 149 155 static std::unique_ptr<AccessCase> getLength(VM&, JSCell* owner, AccessType); 156 static std::unique_ptr<AccessCase> getIntrinsic(VM&, JSCell* owner, JSFunction* intrinsic, PropertyOffset, Structure*, const ObjectPropertyConditionSet&); 150 157 151 158 static std::unique_ptr<AccessCase> fromStructureStubInfo(VM&, JSCell* owner, StructureStubInfo&); … … 174 181 175 182 ObjectPropertyConditionSet conditionSet() const { return m_conditionSet; } 183 JSFunction* intrinsicFunction() const 184 { 185 ASSERT(type() == IntrinsicGetter && m_rareData); 186 return m_rareData->intrinsicFunction.get(); 187 } 188 Intrinsic intrinsic() const 189 { 190 return intrinsicFunction()->intrinsic(); 191 } 176 192 177 193 WatchpointSet* additionalSet() const … … 221 237 bool couldStillSucceed() const; 222 238 239 static bool canEmitIntrinsicGetter(JSFunction*, Structure*); 240 223 241 // If this method returns true, then it's a good idea to remove 'other' from the access once 'this' 224 242 // is added. This method assumes that in case of contradictions, 'this' represents a newer, and so … … 243 261 // Fall through on success, add a jump to the failure list on failure. 244 262 void generate(AccessGenerationState&); 263 void emitIntrinsicGetter(AccessGenerationState&); 245 264 246 265 AccessType m_type { Load }; … … 272 291 } customAccessor; 273 292 WriteBarrier<JSObject> customSlotBase; 293 WriteBarrier<JSFunction> intrinsicFunction; 274 294 }; 275 295 … … 321 341 }; 322 342 343 struct AccessGenerationState { 344 AccessGenerationState() 345 : m_calculatedRegistersForCallAndExceptionHandling(false) 346 , m_needsToRestoreRegistersIfException(false) 347 , m_calculatedCallSiteIndex(false) 348 { 349 } 350 CCallHelpers* jit { nullptr }; 351 ScratchRegisterAllocator* allocator; 352 unsigned numberOfBytesUsedToPreserveReusedRegisters { 0 }; 353 PolymorphicAccess* access { nullptr }; 354 StructureStubInfo* stubInfo { nullptr }; 355 MacroAssembler::JumpList success; 356 MacroAssembler::JumpList failAndRepatch; 357 MacroAssembler::JumpList failAndIgnore; 358 GPRReg baseGPR { InvalidGPRReg }; 359 JSValueRegs valueRegs; 360 GPRReg scratchGPR { InvalidGPRReg }; 361 Vector<std::function<void(LinkBuffer&)>> callbacks; 362 const Identifier* ident; 363 std::unique_ptr<WatchpointsOnStructureStubInfo> watchpoints; 364 Vector<WriteBarrier<JSCell>> weakReferences; 365 366 Watchpoint* addWatchpoint(const ObjectPropertyCondition& = ObjectPropertyCondition()); 367 368 void restoreScratch(); 369 void succeed(); 370 371 void calculateLiveRegistersForCallAndExceptionHandling(); 372 373 void preserveLiveRegistersToStackForCall(); 374 375 void restoreLiveRegistersFromStackForCall(bool isGetter); 376 void restoreLiveRegistersFromStackForCallWithThrownException(); 377 void restoreLiveRegistersFromStackForCall(const RegisterSet& dontRestore); 378 379 const RegisterSet& liveRegistersForCall() 380 { 381 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 382 return m_liveRegistersForCall; 383 } 384 385 CallSiteIndex callSiteIndexForExceptionHandlingOrOriginal(); 386 CallSiteIndex callSiteIndexForExceptionHandling() 387 { 388 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 389 RELEASE_ASSERT(m_needsToRestoreRegistersIfException); 390 RELEASE_ASSERT(m_calculatedCallSiteIndex); 391 return m_callSiteIndex; 392 } 393 394 const HandlerInfo& originalExceptionHandler() const; 395 unsigned numberOfStackBytesUsedForRegisterPreservation() const 396 { 397 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 398 return m_numberOfStackBytesUsedForRegisterPreservation; 399 } 400 401 bool needsToRestoreRegistersIfException() const { return m_needsToRestoreRegistersIfException; } 402 CallSiteIndex originalCallSiteIndex() const; 403 404 private: 405 const RegisterSet& liveRegistersToPreserveAtExceptionHandlingCallSite() 406 { 407 RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling); 408 return m_liveRegistersToPreserveAtExceptionHandlingCallSite; 409 } 410 411 RegisterSet m_liveRegistersToPreserveAtExceptionHandlingCallSite; 412 RegisterSet m_liveRegistersForCall; 413 CallSiteIndex m_callSiteIndex { CallSiteIndex(std::numeric_limits<unsigned>::max()) }; 414 unsigned m_numberOfStackBytesUsedForRegisterPreservation { std::numeric_limits<unsigned>::max() }; 415 bool m_calculatedRegistersForCallAndExceptionHandling : 1; 416 bool m_needsToRestoreRegistersIfException : 1; 417 bool m_calculatedCallSiteIndex : 1; 418 }; 419 323 420 } // namespace JSC 324 421 -
trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.h
r190076 r191215 111 111 const ObjectPropertyConditionSet& conditionSet() const { return m_conditionSet; } 112 112 113 // We don't support intrinsics for Setters (it would be sweet if we did) but we need this for templated helpers. 114 Intrinsic intrinsic() const { return NoIntrinsic; } 115 113 116 PropertyOffset offset() const 114 117 { -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r190896 r191215 2022 2022 case Array::Float64Array: 2023 2023 filter(node->child1(), SpecFloat64Array); 2024 break; 2025 case Array::AnyTypedArray: 2026 filter(node->child1(), SpecTypedArrayView); 2024 2027 break; 2025 2028 default: -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
r188432 r191215 486 486 case Array::Float64Array: 487 487 return speculationChecked(value.m_type, SpecFloat64Array); 488 488 489 case Array::AnyTypedArray: 490 return speculationChecked(value.m_type, SpecTypedArrayView); 491 489 492 case Array::SelectUsingPredictions: 490 493 case Array::Unprofiled: … … 546 549 case Array::Float64Array: 547 550 return "Float64Array"; 551 case Array::AnyTypedArray: 552 return "AnyTypedArray"; 548 553 default: 549 554 // Better to return something then it is to crash. Remember, this method … … 640 645 case Array::Float64Array: 641 646 return TypeFloat64; 647 case Array::AnyTypedArray: 648 RELEASE_ASSERT_NOT_REACHED(); 649 return NotTypedArray; 642 650 default: 643 651 return NotTypedArray; … … 671 679 } 672 680 681 Array::Type refineTypedArrayType(Array::Type oldType, TypedArrayType newType) 682 { 683 if (oldType == Array::Generic) 684 return oldType; 685 Array::Type newArrayType = toArrayType(newType); 686 if (newArrayType == Array::Generic) 687 return newArrayType; 688 689 if (oldType != newArrayType) 690 return Array::AnyTypedArray; 691 return oldType; 692 } 693 673 694 bool permitsBoundsCheckLowering(Array::Type type) 674 695 { … … 686 707 case Array::Float32Array: 687 708 case Array::Float64Array: 709 case Array::AnyTypedArray: 688 710 return true; 689 711 default: -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h
r188432 r191215 78 78 Uint32Array, 79 79 Float32Array, 80 Float64Array 80 Float64Array, 81 AnyTypedArray 81 82 }; 82 83 … … 111 112 TypedArrayType toTypedArrayType(Array::Type); 112 113 Array::Type toArrayType(TypedArrayType); 114 Array::Type refineTypedArrayType(Array::Type, TypedArrayType); 113 115 114 116 bool permitsBoundsCheckLowering(Array::Type); … … 355 357 case Array::ForceExit: 356 358 case Array::Generic: 359 // TypedArrays do not have a self length property as of ES6. 360 case Array::Int8Array: 361 case Array::Int16Array: 362 case Array::Int32Array: 363 case Array::Uint8Array: 364 case Array::Uint8ClampedArray: 365 case Array::Uint16Array: 366 case Array::Uint32Array: 367 case Array::Float32Array: 368 case Array::Float64Array: 357 369 return false; 358 370 case Array::Int32: … … 431 443 return toTypedArrayType(type()); 432 444 } 445 446 bool isSomeTypedArrayView() const 447 { 448 return type() == Array::AnyTypedArray || isTypedView(typedArrayType()); 449 } 433 450 434 451 bool operator==(const ArrayMode& other) const -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r191058 r191215 202 202 // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call. 203 203 template<typename ChecksFunctor> 204 bool handleIntrinsic(int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks); 204 bool handleIntrinsicCall(int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks); 205 template<typename ChecksFunctor> 206 bool handleIntrinsicGetter(int resultOperand, const GetByIdVariant& intrinsicVariant, Node* thisNode, const ChecksFunctor& insertChecks); 205 207 template<typename ChecksFunctor> 206 208 bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks); … … 1591 1593 Intrinsic intrinsic = callee.intrinsicFor(specializationKind); 1592 1594 if (intrinsic != NoIntrinsic) { 1593 if (handleIntrinsic (resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {1595 if (handleIntrinsicCall(resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) { 1594 1596 RELEASE_ASSERT(didInsertChecks); 1595 1597 addToGraph(Phantom, callTargetNode); … … 1981 1983 1982 1984 template<typename ChecksFunctor> 1983 bool ByteCodeParser::handleIntrinsic (int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)1985 bool ByteCodeParser::handleIntrinsicCall(int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks) 1984 1986 { 1985 1987 switch (intrinsic) { 1988 1989 // Intrinsic Functions: 1990 1986 1991 case AbsIntrinsic: { 1987 1992 if (argumentCountIncludingThis == 1) { // Math.abs() … … 2267 2272 return false; 2268 2273 } 2274 } 2275 2276 template<typename ChecksFunctor> 2277 bool ByteCodeParser::handleIntrinsicGetter(int resultOperand, const GetByIdVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks) 2278 { 2279 switch (variant.intrinsic()) { 2280 case TypedArrayByteLengthIntrinsic: { 2281 insertChecks(); 2282 2283 TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType; 2284 Array::Type arrayType = toArrayType(type); 2285 size_t logSize = logElementSize(type); 2286 2287 variant.structureSet().forEach([&] (Structure* structure) { 2288 TypedArrayType curType = structure->classInfo()->typedArrayStorageType; 2289 ASSERT(logSize == logElementSize(curType)); 2290 arrayType = refineTypedArrayType(arrayType, curType); 2291 ASSERT(arrayType != Array::Generic); 2292 }); 2293 2294 Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType).asWord()), thisNode); 2295 2296 if (!logSize) { 2297 set(VirtualRegister(resultOperand), lengthNode); 2298 return true; 2299 } 2300 2301 // We can use a BitLShift here because typed arrays will never have a byteLength 2302 // that overflows int32. 2303 Node* shiftNode = jsConstant(jsNumber(logSize)); 2304 set(VirtualRegister(resultOperand), addToGraph(BitLShift, lengthNode, shiftNode)); 2305 2306 return true; 2307 } 2308 2309 case TypedArrayLengthIntrinsic: { 2310 insertChecks(); 2311 2312 TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType; 2313 Array::Type arrayType = toArrayType(type); 2314 2315 variant.structureSet().forEach([&] (Structure* structure) { 2316 TypedArrayType curType = structure->classInfo()->typedArrayStorageType; 2317 arrayType = refineTypedArrayType(arrayType, curType); 2318 ASSERT(arrayType != Array::Generic); 2319 }); 2320 2321 set(VirtualRegister(resultOperand), addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType).asWord()), thisNode)); 2322 2323 return true; 2324 2325 } 2326 2327 case TypedArrayByteOffsetIntrinsic: { 2328 insertChecks(); 2329 2330 TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType; 2331 Array::Type arrayType = toArrayType(type); 2332 2333 variant.structureSet().forEach([&] (Structure* structure) { 2334 TypedArrayType curType = structure->classInfo()->typedArrayStorageType; 2335 arrayType = refineTypedArrayType(arrayType, curType); 2336 ASSERT(arrayType != Array::Generic); 2337 }); 2338 2339 set(VirtualRegister(resultOperand), addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType).asWord()), thisNode)); 2340 2341 return true; 2342 } 2343 2344 default: 2345 return false; 2346 } 2347 RELEASE_ASSERT_NOT_REACHED(); 2269 2348 } 2270 2349 … … 2693 2772 SpeculatedType loadPrediction; 2694 2773 NodeType loadOp; 2695 if (variant.callLinkStatus() ) {2774 if (variant.callLinkStatus() || variant.intrinsic() != NoIntrinsic) { 2696 2775 loadPrediction = SpecCellOther; 2697 2776 loadOp = GetGetterSetterByOffset; … … 2764 2843 // of checks and those checks are not watchpointable. 2765 2844 for (const GetByIdVariant& variant : getByIdStatus.variants()) { 2845 if (variant.intrinsic() != NoIntrinsic) { 2846 set(VirtualRegister(destinationOperand), 2847 addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base)); 2848 return; 2849 } 2850 2766 2851 if (variant.conditionSet().isEmpty()) { 2767 2852 cases.append( … … 2806 2891 if (m_graph.compilation()) 2807 2892 m_graph.compilation()->noticeInlinedGetById(); 2808 2809 if (!variant.callLinkStatus() ) {2893 2894 if (!variant.callLinkStatus() && variant.intrinsic() == NoIntrinsic) { 2810 2895 set(VirtualRegister(destinationOperand), loadedValue); 2811 2896 return; … … 2813 2898 2814 2899 Node* getter = addToGraph(GetGetter, loadedValue); 2815 2900 2901 if (handleIntrinsicGetter(destinationOperand, variant, base, 2902 [&] () { 2903 addToGraph(CheckCell, OpInfo(m_graph.freeze(variant.intrinsicFunction())), getter, base); 2904 })) { 2905 addToGraph(Phantom, getter); 2906 return; 2907 } 2908 2909 if (variant.intrinsic() != NoIntrinsic) 2910 ASSERT(variant.intrinsic() == NoIntrinsic); 2911 2816 2912 // Make a call. We don't try to get fancy with using the smallest operand number because 2817 2913 // the stack layout phase should compress the stack anyway. -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r190896 r191215 576 576 def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), LazyNode(node)); 577 577 return; 578 // We should not get an AnyTypedArray in a GetByVal as AnyTypedArray is only created from intrinsics, which 579 // are only added from Inline Caching a GetById. 580 case Array::AnyTypedArray: 581 DFG_CRASH(graph, node, "impossible array mode for get"); 582 return; 578 583 } 579 584 RELEASE_ASSERT_NOT_REACHED(); … … 680 685 // https://bugs.webkit.org/show_bug.cgi?id=134737 681 686 return; 687 case Array::AnyTypedArray: 682 688 case Array::String: 683 689 case Array::DirectArguments: … … 819 825 def(PureValue(node, mode.asWord())); 820 826 return; 821 827 822 828 case Array::DirectArguments: 823 829 case Array::ScopedArguments: … … 825 831 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node)); 826 832 return; 827 833 828 834 default: 829 ASSERT(mode. typedArrayType() != NotTypedArray);835 ASSERT(mode.isSomeTypedArrayView()); 830 836 read(MiscFields); 831 837 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), LazyNode(node)); -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r190896 r191215 1037 1037 break; 1038 1038 } 1039 if (uid == vm().propertyNames->byteLength.impl()) {1040 attemptToMakeGetTypedArrayByteLength(node);1041 break;1042 }1043 if (uid == vm().propertyNames->byteOffset.impl()) {1044 attemptToMakeGetTypedArrayByteOffset(node);1045 break;1046 }1047 1039 } 1048 1040 fixEdge<CellUse>(node->child1()); … … 1164 1156 } 1165 1157 1166 case GetArrayLength: 1158 case GetArrayLength: { 1159 fixEdge<KnownCellUse>(node->child1()); 1160 break; 1161 } 1162 1163 case GetTypedArrayByteOffset: { 1164 fixEdge<KnownCellUse>(node->child1()); 1165 break; 1166 } 1167 1167 1168 case Phi: 1168 1169 case Upsilon: 1169 1170 case GetIndexedPropertyStorage: 1170 case GetTypedArrayByteOffset:1171 1171 case LastNodeType: 1172 1172 case CheckTierUpInLoop: … … 2065 2065 return true; 2066 2066 } 2067 2068 bool attemptToMakeGetTypedArrayByteLength(Node* node) 2069 { 2070 if (!isInt32Speculation(node->prediction())) 2071 return false; 2072 2073 TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction()); 2074 if (!isTypedView(type)) 2075 return false; 2076 2077 if (elementSize(type) == 1) { 2078 convertToGetArrayLength(node, ArrayMode(toArrayType(type))); 2079 return true; 2080 } 2081 2082 Node* length = prependGetArrayLength( 2083 node->origin, node->child1().node(), ArrayMode(toArrayType(type))); 2084 2085 Node* shiftAmount = m_insertionSet.insertNode( 2086 m_indexInBlock, SpecInt32, JSConstant, node->origin, 2087 OpInfo(m_graph.freeze(jsNumber(logElementSize(type))))); 2088 2089 // We can use a BitLShift here because typed arrays will never have a byteLength 2090 // that overflows int32. 2091 node->setOp(BitLShift); 2092 node->clearFlags(NodeMustGenerate); 2093 observeUseKindOnNode(length, Int32Use); 2094 observeUseKindOnNode(shiftAmount, Int32Use); 2095 node->child1() = Edge(length, Int32Use); 2096 node->child2() = Edge(shiftAmount, Int32Use); 2097 return true; 2098 } 2099 2067 2100 2068 void convertToGetArrayLength(Node* node, ArrayMode arrayMode) 2101 2069 { … … 2118 2086 m_indexInBlock, SpecInt32, GetArrayLength, origin, 2119 2087 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage)); 2120 }2121 2122 bool attemptToMakeGetTypedArrayByteOffset(Node* node)2123 {2124 if (!isInt32Speculation(node->prediction()))2125 return false;2126 2127 TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());2128 if (!isTypedView(type))2129 return false;2130 2131 checkArray(2132 ArrayMode(toArrayType(type)), node->origin, node->child1().node(),2133 0, neverNeedsStorage);2134 2135 node->setOp(GetTypedArrayByteOffset);2136 node->clearFlags(NodeMustGenerate);2137 fixEdge<KnownCellUse>(node->child1());2138 return true;2139 2088 } 2140 2089 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r190827 r191215 1216 1216 JSArrayBufferView* Graph::tryGetFoldableView(JSValue value, ArrayMode arrayMode) 1217 1217 { 1218 if (arrayMode.type dArrayType() == NotTypedArray)1218 if (arrayMode.type() != Array::AnyTypedArray && arrayMode.typedArrayType() == NotTypedArray) 1219 1219 return nullptr; 1220 1220 return tryGetFoldableView(value); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r190896 r191215 231 231 } 232 232 233 case GetTypedArrayByteOffset: 234 case GetArrayLength: { 235 changed |= setPrediction(SpecInt32); 236 break; 237 } 238 233 239 case StringCharCodeAt: { 234 240 changed |= setPrediction(SpecInt32); … … 541 547 542 548 case PutByValAlias: 543 case GetArrayLength:544 case GetTypedArrayByteOffset:545 549 case DoubleAsInt32: 546 550 case GetLocalUnlinked: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r191058 r191215 768 768 769 769 switch (node->arrayMode().type()) { 770 case Array::AnyTypedArray: 770 771 case Array::String: 771 772 RELEASE_ASSERT_NOT_REACHED(); // Should have been a Phantom(String:) … … 4666 4667 } 4667 4668 default: { 4668 ASSERT( isTypedView(node->arrayMode().typedArrayType()));4669 ASSERT(node->arrayMode().isSomeTypedArrayView()); 4669 4670 SpeculateCellOperand base(this, node->child1()); 4670 4671 GPRTemporary result(this, Reuse, base); -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r190896 r191215 252 252 break; 253 253 default: 254 if ( isTypedView(node->arrayMode().typedArrayType()))254 if (node->arrayMode().isSomeTypedArrayView()) 255 255 break; 256 256 return CannotCompile; -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r191175 r191215 2411 2411 2412 2412 default: 2413 if ( isTypedView(m_node->arrayMode().typedArrayType())) {2413 if (m_node->arrayMode().isSomeTypedArrayView()) { 2414 2414 setInt32( 2415 2415 m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length)); -
trunk/Source/JavaScriptCore/jit/Repatch.cpp
r191058 r191215 225 225 226 226 std::unique_ptr<AccessCase> newCase; 227 JSFunction* getter = nullptr; 228 ObjectPropertyConditionSet conditionSet; 229 JSCell* baseCell = baseValue.asCell(); 230 Structure* structure = baseCell->structure(vm); 231 232 if (slot.isCacheableGetter()) 233 getter = jsDynamicCast<JSFunction*>(slot.getterSetter()->getter()); 227 234 228 235 if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) … … 230 237 else if (isJSString(baseValue) && propertyName == exec->propertyNames().length) 231 238 newCase = AccessCase::getLength(vm, codeBlock, AccessCase::StringLength); 232 else { 239 else if (getter && AccessCase::canEmitIntrinsicGetter(getter, structure)) { 240 if (slot.slotBase() != baseValue) { 241 conditionSet = generateConditionsForPrototypePropertyHit(vm, codeBlock->ownerExecutable(), exec, structure, slot.slotBase(), propertyName.impl()); 242 if (!conditionSet.isValid()) 243 return GiveUpOnCache; 244 } 245 246 newCase = AccessCase::getIntrinsic(vm, codeBlock, getter, slot.cachedOffset(), structure, conditionSet); 247 248 } else { 233 249 if (!slot.isCacheable() && !slot.isUnset()) 234 250 return GiveUpOnCache; 235 236 JSCell* baseCell = baseValue.asCell();237 Structure* structure = baseCell->structure(vm);238 251 239 252 bool loadTargetFromProxy = false; … … 266 279 267 280 PropertyOffset offset = slot.isUnset() ? invalidOffset : slot.cachedOffset(); 268 269 ObjectPropertyConditionSet conditionSet; 281 270 282 if (slot.isUnset() || slot.slotBase() != baseValue) { 271 283 if (structure->typeInfo().prohibitsPropertyCaching() || structure->isDictionary()) -
trunk/Source/JavaScriptCore/runtime/Intrinsic.h
r184260 r191215 30 30 31 31 enum Intrinsic { 32 // Call intrinsics. 32 33 NoIntrinsic, 33 34 AbsIntrinsic, … … 55 56 FRoundIntrinsic, 56 57 58 // Getter intrinsics. 59 TypedArrayLengthIntrinsic, 60 TypedArrayByteLengthIntrinsic, 61 TypedArrayByteOffsetIntrinsic, 62 57 63 // Debugging intrinsics. These are meant to be used as testing hacks within 58 64 // jsc.cpp and should never be exposed to users. -
trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp
r190896 r191215 141 141 { 142 142 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object); 143 if (propertyName == exec->propertyNames().byteOffset) {144 slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->byteOffset()));145 return true;146 }147 143 148 144 if (propertyName == exec->propertyNames().buffer) { … … 161 157 { 162 158 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell); 163 if (propertyName == exec->propertyNames().byteLength 164 || propertyName == exec->propertyNames().byteOffset 165 || propertyName == exec->propertyNames().buffer) { 159 if (propertyName == exec->propertyNames().buffer) { 166 160 reject(exec, slot.isStrictMode(), "Attempting to write to read-only typed array property."); 167 161 return; … … 176 170 { 177 171 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object); 178 if (propertyName == exec->propertyNames().byteLength 179 || propertyName == exec->propertyNames().byteOffset 180 || propertyName == exec->propertyNames().buffer) 172 if (propertyName == exec->propertyNames().buffer) 181 173 return reject(exec, shouldThrow, "Attempting to define read-only typed array property."); 182 174 … … 188 180 { 189 181 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell); 190 if (propertyName == exec->propertyNames().byteLength 191 || propertyName == exec->propertyNames().byteOffset 192 || propertyName == exec->propertyNames().buffer) 182 if (propertyName == exec->propertyNames().buffer) 193 183 return false; 194 184 … … 201 191 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object); 202 192 203 // length/byteOffset/byteLength are DontEnum, at least in Firefox. 204 if (mode.includeDontEnumProperties()) { 205 array.add(exec->propertyNames().byteOffset); 206 array.add(exec->propertyNames().byteLength); 193 if (mode.includeDontEnumProperties()) 207 194 array.add(exec->propertyNames().buffer); 208 } 195 209 196 210 197 Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode); -
trunk/Source/JavaScriptCore/runtime/JSDataView.cpp
r191059 r191215 31 31 #include "Error.h" 32 32 #include "JSCInlines.h" 33 #include "Reject.h" 33 34 34 35 namespace JSC { … … 103 104 return true; 104 105 } 106 if (propertyName == exec->propertyNames().byteOffset) { 107 slot.setValue(thisObject, DontEnum | ReadOnly, jsNumber(thisObject->byteOffset())); 108 return true; 109 } 110 111 return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); 112 } 113 114 void JSDataView::put( 115 JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, 116 PutPropertySlot& slot) 117 { 118 JSDataView* thisObject = jsCast<JSDataView*>(cell); 119 if (propertyName == exec->propertyNames().byteLength 120 || propertyName == exec->propertyNames().byteOffset) { 121 reject(exec, slot.isStrictMode(), "Attempting to write to read-only typed array property."); 122 return; 123 } 124 125 Base::put(thisObject, exec, propertyName, value, slot); 126 } 127 128 bool JSDataView::defineOwnProperty( 129 JSObject* object, ExecState* exec, PropertyName propertyName, 130 const PropertyDescriptor& descriptor, bool shouldThrow) 131 { 132 JSDataView* thisObject = jsCast<JSDataView*>(object); 133 if (propertyName == exec->propertyNames().byteLength 134 || propertyName == exec->propertyNames().byteOffset) 135 return reject(exec, shouldThrow, "Attempting to define read-only typed array property."); 136 137 return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); 138 } 139 140 bool JSDataView::deleteProperty( 141 JSCell* cell, ExecState* exec, PropertyName propertyName) 142 { 143 JSDataView* thisObject = jsCast<JSDataView*>(cell); 144 if (propertyName == exec->propertyNames().byteLength 145 || propertyName == exec->propertyNames().byteOffset) 146 return false; 147 148 return Base::deleteProperty(thisObject, exec, propertyName); 149 } 150 151 void JSDataView::getOwnNonIndexPropertyNames( 152 JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode) 153 { 154 JSDataView* thisObject = jsCast<JSDataView*>(object); 105 155 106 return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); 156 if (mode.includeDontEnumProperties()) { 157 array.add(exec->propertyNames().byteOffset); 158 array.add(exec->propertyNames().byteLength); 159 } 160 161 Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode); 107 162 } 108 163 -
trunk/Source/JavaScriptCore/runtime/JSDataView.h
r191059 r191215 60 60 protected: 61 61 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); 62 static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); 63 static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); 64 static bool deleteProperty(JSCell*, ExecState*, PropertyName); 65 66 static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 62 67 63 68 static ArrayBuffer* slowDownAndWasteMemory(JSArrayBufferView*); -
trunk/Source/JavaScriptCore/runtime/JSFunction.h
r190198 r191215 85 85 ExecutableBase* executable() const { return m_executable.get(); } 86 86 87 // To call either of these methods include Executable.h87 // To call any of these methods include JSFunctionInlines.h 88 88 bool isHostFunction() const; 89 89 FunctionExecutable* jsExecutable() const; 90 Intrinsic intrinsic() const; 90 91 91 92 JS_EXPORT_PRIVATE const SourceCode* sourceCode() const; -
trunk/Source/JavaScriptCore/runtime/JSFunctionInlines.h
r189123 r191215 74 74 } 75 75 76 inline Intrinsic JSFunction::intrinsic() const 77 { 78 return executable()->intrinsic(); 79 } 80 76 81 inline bool JSFunction::isBuiltinFunction() const 77 82 { -
trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h
r191059 r191215 278 278 static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); 279 279 280 static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);281 280 static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 282 281 -
trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h
r190896 r191215 294 294 { 295 295 JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object); 296 if (propertyName == exec->propertyNames().length) { 297 slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->length())); 298 return true; 299 } 300 301 if (propertyName == exec->propertyNames().byteLength) { 302 slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->byteLength())); 303 return true; 304 } 305 296 306 297 Optional<uint32_t> index = parseIndex(propertyName); 307 298 if (index && thisObject->canGetIndexQuickly(index.value())) { … … 320 311 JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell); 321 312 322 if (propertyName == exec->propertyNames().length) {323 // Firefox appears to simply ignore attempts to store to the length property.324 // Even in strict mode. I will do the same.325 return;326 }327 328 313 if (Optional<uint32_t> index = parseIndex(propertyName)) { 329 314 putByIndex(thisObject, exec, index.value(), value, slot.isStrictMode()); … … 344 329 // defineOwnProperty for indexed properties on typed arrays, even if they're out 345 330 // of bounds. 346 if (p ropertyName == exec->propertyNames().length || parseIndex(propertyName))331 if (parseIndex(propertyName)) 347 332 return reject(exec, shouldThrow, "Attempting to write to a read-only typed array property."); 348 333 … … 356 341 JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell); 357 342 358 if (p ropertyName == exec->propertyNames().length || parseIndex(propertyName))343 if (parseIndex(propertyName)) 359 344 return false; 360 345 … … 406 391 407 392 return false; 408 }409 410 template<typename Adaptor>411 void JSGenericTypedArrayView<Adaptor>::getOwnNonIndexPropertyNames(412 JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)413 {414 JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);415 416 if (mode.includeDontEnumProperties())417 array.add(exec->propertyNames().length);418 419 Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode);420 393 } 421 394 -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r190904 r191215 2288 2288 } 2289 2289 2290 void JSObject::putDirectNativeIntrinsicGetter(VM& vm, JSGlobalObject* globalObject, Identifier name, NativeFunction nativeFunction, Intrinsic intrinsic, unsigned attributes) 2291 { 2292 GetterSetter* accessor = GetterSetter::create(vm, globalObject); 2293 JSFunction* function = JSFunction::create(vm, globalObject, 0, name.string(), nativeFunction, intrinsic); 2294 accessor->setGetter(vm, globalObject, function); 2295 putDirectNonIndexAccessor(vm, name, accessor, attributes); 2296 } 2297 2290 2298 void JSObject::putDirectNativeFunction(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, unsigned functionLength, NativeFunction nativeFunction, Intrinsic intrinsic, unsigned attributes) 2291 2299 { -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r190896 r191215 596 596 void putDirectUndefined(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); } 597 597 598 JS_EXPORT_PRIVATE void putDirectNativeIntrinsicGetter(VM&, JSGlobalObject*, Identifier, NativeFunction, Intrinsic, unsigned attributes); 598 599 JS_EXPORT_PRIVATE void putDirectNativeFunction(VM&, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes); 599 600 JS_EXPORT_PRIVATE JSFunction* putDirectBuiltinFunction(VM&, JSGlobalObject*, const PropertyName&, FunctionExecutable*, unsigned attributes); … … 1472 1473 1473 1474 // Helper for defining native getters on properties. 1474 #define JSC_NATIVE_ GETTER(jsName, cppName, attributes, length) do {\1475 Identifier ident = makeIdentifier(vm, (jsName));\1476 GetterSetter* accessor = GetterSetter::create(vm, globalObject);\1477 JSFunction* function = JSFunction::create(vm, globalObject, (length), ident.string(), (cppName)); \1478 accessor->setGetter(vm, globalObject, function); \ 1479 putDirectNonIndexAccessor(vm, ident, accessor, (attributes) | Accessor);\1480 } while (false)1475 #define JSC_NATIVE_INTRINSIC_GETTER(jsName, cppName, attributes, intrinsic) \ 1476 putDirectNativeIntrinsicGetter(\ 1477 vm, globalObject, makeIdentifier(vm, (jsName)), (cppName), \ 1478 (intrinsic), ((attributes) | Accessor)) 1479 1480 #define JSC_NATIVE_GETTER(jsName, cppName, attributes) \ 1481 JSC_NATIVE_INTRINSIC_GETTER((jsName), (cppName), (attributes), NoIntrinsic) 1481 1482 1482 1483 -
trunk/Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.cpp
r191059 r191215 214 214 ASSERT(inherits(info())); 215 215 216 JSC_NATIVE_ GETTER(vm.propertyNames->byteLength, typedArrayViewProtoGetterFuncByteLength, DontEnum | ReadOnly | DontDelete, 0);217 JSC_NATIVE_ GETTER(vm.propertyNames->byteOffset, typedArrayViewProtoGetterFuncByteOffset, DontEnum | ReadOnly | DontDelete, 0);216 JSC_NATIVE_INTRINSIC_GETTER(vm.propertyNames->byteLength, typedArrayViewProtoGetterFuncByteLength, DontEnum | ReadOnly | DontDelete, TypedArrayByteLengthIntrinsic); 217 JSC_NATIVE_INTRINSIC_GETTER(vm.propertyNames->byteOffset, typedArrayViewProtoGetterFuncByteOffset, DontEnum | ReadOnly | DontDelete, TypedArrayByteOffsetIntrinsic); 218 218 JSC_NATIVE_FUNCTION("copyWithin", typedArrayViewProtoFuncCopyWithin, DontEnum, 2); 219 219 JSC_BUILTIN_FUNCTION("every", typedArrayPrototypeEveryCodeGenerator, DontEnum); … … 229 229 JSC_NATIVE_FUNCTION(vm.propertyNames->keys, typedArrayViewProtoFuncKeys, DontEnum, 0); 230 230 JSC_NATIVE_FUNCTION("lastIndexOf", typedArrayViewProtoFuncLastIndexOf, DontEnum, 1); 231 JSC_NATIVE_ GETTER(vm.propertyNames->length, typedArrayViewProtoGetterFuncLength, DontEnum | ReadOnly | DontDelete, 0);231 JSC_NATIVE_INTRINSIC_GETTER(vm.propertyNames->length, typedArrayViewProtoGetterFuncLength, DontEnum | ReadOnly | DontDelete, TypedArrayLengthIntrinsic); 232 232 JSC_BUILTIN_FUNCTION("map", typedArrayPrototypeMapCodeGenerator, DontEnum); 233 233 JSC_BUILTIN_FUNCTION("reduce", typedArrayPrototypeReduceCodeGenerator, DontEnum);
Note:
See TracChangeset
for help on using the changeset viewer.