WebKit Bugzilla
Attachment 340773 Details for
Bug 185682
: [JSC] JSC should have consistent InById IC
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-185682-20180519234238.patch (text/plain), 83.42 KB, created by
Yusuke Suzuki
on 2018-05-19 07:42:40 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2018-05-19 07:42:40 PDT
Size:
83.42 KB
patch
obsolete
>Subversion Revision: 231988 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 71e84aa7c02bf410fbde6b9568a5fe3773454f32..747f0396f09ae4d90d944ba1f52e9f6fd49113ec 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,145 @@ >+2018-05-19 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [JSC] JSC should have consistent InById IC >+ https://bugs.webkit.org/show_bug.cgi?id=185682 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Current our op_in IC is adhoc: It is only emitted in DFG and FTL layers, >+ when we found that DFG::In's parameter is constant string. We should >+ align this IC to the other ById ICs to clean up and remove adhoc code >+ in DFG and FTL. >+ >+ This patch cleans up our "In" IC by aligning it to the other ById ICs. >+ We split op_in bytecode to op_in_by_id and op_in_by_val. op_in_by_val >+ is the same to the original op_in. For op_in_by_id, we use JITInByIdGenerator >+ to emit InById IC code. In addition, our JITInByIdGenerator and op_in_by_id >+ has a inline access cache for own property case, which is the same to >+ JITGetByIdGenerator. >+ >+ And we split DFG::In to DFG::InById and DFG::InByVal. InByVal is the same >+ to the original In DFG node. DFG AI attempts to lower InByVal to InById >+ if AI figured out that the property name is a constant string. And in >+ InById node, we use JITInByIdGenerator code. >+ >+ This patch cleans up DFG and FTL's adhoc In IC code. >+ >+ In a subsequent patch, we should introduce InByIdStatus to optimize >+ InById in DFG and FTL. We would like to have a new InByIdStatus instead of >+ reusing GetByIdStatus since GetByIdStatus becomes too complicated, and >+ AccessCase::Types are different from them (AccessCase::InHit / InMiss). >+ >+ * bytecode/AccessCase.cpp: >+ (JSC::AccessCase::fromStructureStubInfo): >+ * bytecode/BytecodeDumper.cpp: >+ (JSC::BytecodeDumper<Block>::printInByIdCacheStatus): >+ (JSC::BytecodeDumper<Block>::dumpBytecode): >+ * bytecode/BytecodeDumper.h: >+ * bytecode/BytecodeList.json: >+ * bytecode/BytecodeUseDef.h: >+ (JSC::computeUsesForBytecodeOffset): >+ (JSC::computeDefsForBytecodeOffset): >+ * bytecode/CodeBlock.cpp: >+ (JSC::CodeBlock::finishCreation): >+ * bytecode/InlineAccess.cpp: >+ (JSC::InlineAccess::generateSelfInAccess): >+ * bytecode/InlineAccess.h: >+ * bytecode/StructureStubInfo.cpp: >+ (JSC::StructureStubInfo::initInByIdSelf): >+ (JSC::StructureStubInfo::deref): >+ (JSC::StructureStubInfo::aboutToDie): >+ (JSC::StructureStubInfo::reset): >+ (JSC::StructureStubInfo::visitWeakReferences): >+ (JSC::StructureStubInfo::propagateTransitions): >+ * bytecode/StructureStubInfo.h: >+ (JSC::StructureStubInfo::patchableJump): >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::emitInByVal): >+ (JSC::BytecodeGenerator::emitInById): >+ (JSC::BytecodeGenerator::emitIn): Deleted. >+ * bytecompiler/BytecodeGenerator.h: >+ * bytecompiler/NodesCodegen.cpp: >+ (JSC::InNode::emitBytecode): >+ * dfg/DFGAbstractInterpreterInlines.h: >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): >+ * dfg/DFGByteCodeParser.cpp: >+ (JSC::DFG::ByteCodeParser::handleInById): >+ (JSC::DFG::ByteCodeParser::parseBlock): >+ * dfg/DFGCapabilities.cpp: >+ (JSC::DFG::capabilityLevel): >+ * dfg/DFGClobberize.h: >+ (JSC::DFG::clobberize): >+ * dfg/DFGConstantFoldingPhase.cpp: >+ (JSC::DFG::ConstantFoldingPhase::foldConstants): >+ * dfg/DFGDoesGC.cpp: >+ (JSC::DFG::doesGC): >+ * dfg/DFGFixupPhase.cpp: >+ (JSC::DFG::FixupPhase::fixupNode): >+ * dfg/DFGJITCompiler.cpp: >+ (JSC::DFG::JITCompiler::link): >+ * dfg/DFGJITCompiler.h: >+ (JSC::DFG::JITCompiler::addInById): >+ (JSC::DFG::InRecord::InRecord): Deleted. >+ (JSC::DFG::JITCompiler::addIn): Deleted. >+ * dfg/DFGNode.h: >+ (JSC::DFG::Node::convertToInById): >+ (JSC::DFG::Node::hasIdentifier): >+ (JSC::DFG::Node::hasArrayMode): >+ * dfg/DFGNodeType.h: >+ * dfg/DFGPredictionPropagationPhase.cpp: >+ * dfg/DFGSafeToExecute.h: >+ (JSC::DFG::safeToExecute): >+ * dfg/DFGSpeculativeJIT.cpp: >+ (JSC::DFG::SpeculativeJIT::compileInById): >+ (JSC::DFG::SpeculativeJIT::compileInByVal): >+ (JSC::DFG::SpeculativeJIT::compileIn): Deleted. >+ * dfg/DFGSpeculativeJIT.h: >+ * dfg/DFGSpeculativeJIT32_64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGSpeculativeJIT64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * ftl/FTLCapabilities.cpp: >+ (JSC::FTL::canCompile): >+ * ftl/FTLLowerDFGToB3.cpp: >+ (JSC::FTL::DFG::LowerDFGToB3::compileNode): >+ (JSC::FTL::DFG::LowerDFGToB3::compileInByVal): >+ (JSC::FTL::DFG::LowerDFGToB3::compileInById): >+ (JSC::FTL::DFG::LowerDFGToB3::compileIn): Deleted. >+ * jit/ICStats.h: >+ * jit/JIT.cpp: >+ (JSC::JIT::JIT): >+ (JSC::JIT::privateCompileMainPass): >+ (JSC::JIT::privateCompileSlowCases): >+ (JSC::JIT::link): >+ * jit/JIT.h: >+ * jit/JITInlineCacheGenerator.cpp: >+ (JSC::JITInByIdGenerator::JITInByIdGenerator): >+ (JSC::JITInByIdGenerator::generateFastPath): >+ * jit/JITInlineCacheGenerator.h: >+ (JSC::JITInByIdGenerator::JITInByIdGenerator): >+ * jit/JITOperations.cpp: >+ * jit/JITOperations.h: >+ * jit/JITPropertyAccess.cpp: >+ (JSC::JIT::emit_op_in_by_id): >+ (JSC::JIT::emitSlow_op_in_by_id): >+ * jit/Repatch.cpp: >+ (JSC::tryCacheInByID): >+ (JSC::repatchInByID): >+ (JSC::resetInByID): >+ (JSC::tryCacheIn): Deleted. >+ (JSC::repatchIn): Deleted. >+ (JSC::resetIn): Deleted. >+ * jit/Repatch.h: >+ * llint/LowLevelInterpreter.asm: >+ * llint/LowLevelInterpreter64.asm: >+ * parser/NodeConstructors.h: >+ (JSC::InNode::InNode): >+ * runtime/CommonSlowPaths.cpp: >+ (JSC::SLOW_PATH_DECL): >+ * runtime/CommonSlowPaths.h: >+ (JSC::CommonSlowPaths::opInByVal): >+ (JSC::CommonSlowPaths::opIn): Deleted. >+ > 2018-05-18 Mark Lam <mark.lam@apple.com> > > Add missing exception check. >diff --git a/Source/JavaScriptCore/bytecode/AccessCase.cpp b/Source/JavaScriptCore/bytecode/AccessCase.cpp >index e3239a15e4533c87c22291c2626a168a17b373d1..3e772bc9069ca8838504680c8c03f926cd581c35 100644 >--- a/Source/JavaScriptCore/bytecode/AccessCase.cpp >+++ b/Source/JavaScriptCore/bytecode/AccessCase.cpp >@@ -118,6 +118,9 @@ std::unique_ptr<AccessCase> AccessCase::fromStructureStubInfo( > case CacheType::PutByIdReplace: > return AccessCase::create(vm, owner, Replace, stubInfo.u.byIdSelf.offset, stubInfo.u.byIdSelf.baseObjectStructure.get()); > >+ case CacheType::InByIdSelf: >+ return AccessCase::create(vm, owner, InHit, stubInfo.u.byIdSelf.offset, stubInfo.u.byIdSelf.baseObjectStructure.get()); >+ > default: > return nullptr; > } >@@ -555,10 +558,7 @@ void AccessCase::generateWithGuard( > jit.move(baseGPR, valueGPR); > > CCallHelpers::Label loop(&jit); >- failAndIgnore = jit.branch8( >- CCallHelpers::Equal, >- CCallHelpers::Address(valueGPR, JSCell::typeInfoTypeOffset()), >- CCallHelpers::TrustedImm32(ProxyObjectType)); >+ failAndIgnore = jit.branchIfType(valueGPR, ProxyObjectType); > > jit.emitLoadStructure(vm, valueGPR, scratch2GPR, scratchGPR); > #if USE(JSVALUE64) >diff --git a/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp b/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp >index abe9a8a282edf4e78a463830f350b76f98d0f50f..3f9c59e6b6dc8159c48d5157a14515aa897fb667 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp >+++ b/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp >@@ -551,6 +551,59 @@ void BytecodeDumper<Block>::printPutByIdCacheStatus(PrintStream& out, int locati > #endif > } > >+template<class Block> >+void BytecodeDumper<Block>::printInByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map) >+{ >+ const auto* instruction = instructionsBegin() + location; >+ >+ const Identifier& ident = identifier(instruction[3].u.operand); >+ >+ UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations. >+ >+#if ENABLE(JIT) >+ if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) { >+ StructureStubInfo& stubInfo = *stubPtr; >+ if (stubInfo.resetByGC) >+ out.print(" (Reset By GC)"); >+ >+ out.printf(" jit("); >+ >+ Structure* baseStructure = nullptr; >+ PolymorphicAccess* stub = nullptr; >+ >+ switch (stubInfo.cacheType) { >+ case CacheType::InByIdSelf: >+ out.printf("self"); >+ baseStructure = stubInfo.u.byIdSelf.baseObjectStructure.get(); >+ break; >+ case CacheType::Stub: >+ out.printf("stub"); >+ stub = stubInfo.u.stub; >+ break; >+ case CacheType::Unset: >+ out.printf("unset"); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ >+ if (baseStructure) { >+ out.printf(", "); >+ dumpStructure(out, "struct", baseStructure, ident); >+ } >+ >+ if (stub) >+ out.print(", ", *stub); >+ >+ out.printf(")"); >+ } >+#else >+ UNUSED_PARAM(out); >+ UNUSED_PARAM(map); >+#endif >+} >+ > #if ENABLE(JIT) > template<typename Block> > void BytecodeDumper<Block>::dumpCallLinkStatus(PrintStream&, unsigned, const CallLinkInfoMap&) >@@ -1012,8 +1065,17 @@ void BytecodeDumper<Block>::dumpBytecode(PrintStream& out, const typename Block: > printUnaryOp(out, location, it, "is_function"); > break; > } >- case op_in: { >- printBinaryOp(out, location, it, "in"); >+ case op_in_by_id: { >+ int r0 = (++it)->u.operand; >+ int r1 = (++it)->u.operand; >+ int id0 = (++it)->u.operand; >+ printLocationAndOp(out, location, it, "in_by_id"); >+ out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data()); >+ printInByIdCacheStatus(out, location, stubInfos); >+ break; >+ } >+ case op_in_by_val: { >+ printBinaryOp(out, location, it, "in_by_val"); > dumpArrayProfiling(out, it, hasPrintedProfiling); > break; > } >diff --git a/Source/JavaScriptCore/bytecode/BytecodeDumper.h b/Source/JavaScriptCore/bytecode/BytecodeDumper.h >index 7cd08c95217d4fc5abb7c3478661f96f78663880..5e8943ef13e26a2fdebecfe9aae4acdd5841364d 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeDumper.h >+++ b/Source/JavaScriptCore/bytecode/BytecodeDumper.h >@@ -71,6 +71,7 @@ class BytecodeDumper { > void printGetByIdOp(PrintStream& out, int location, const Instruction*& it); > void printGetByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&); > void printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&); >+ void printInByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&); > enum CacheDumpMode { DumpCaches, DontDumpCaches }; > void printCallOp(PrintStream& out, int location, const Instruction*& it, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&); > void printPutByIdOp(PrintStream& out, int location, const Instruction*& it, const char* op); >diff --git a/Source/JavaScriptCore/bytecode/BytecodeList.json b/Source/JavaScriptCore/bytecode/BytecodeList.json >index 5628df5b462163eb296321fe858d03b6d9f76e55..16f1fb60c3d640bdac9bfa27b6c753f67ffbdc14 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeList.json >+++ b/Source/JavaScriptCore/bytecode/BytecodeList.json >@@ -80,7 +80,8 @@ > { "name" : "op_is_object_or_null", "length" : 3 }, > { "name" : "op_is_function", "length" : 3 }, > { "name" : "op_is_cell_with_type", "length" : 4 }, >- { "name" : "op_in", "length" : 5 }, >+ { "name" : "op_in_by_val", "length" : 5 }, >+ { "name" : "op_in_by_id", "length" : 4 }, > { "name" : "op_get_array_length", "length" : 9 }, > { "name" : "op_get_by_id", "length" : 9 }, > { "name" : "op_get_by_id_proto_load", "length" : 9 }, >diff --git a/Source/JavaScriptCore/bytecode/BytecodeUseDef.h b/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >index 701d36cfac451b3c88235661a105717203580ddf..db522ac2e711a49b3f2d92de8ca28bceb531e32e 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >+++ b/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >@@ -186,6 +186,7 @@ void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instructi > case op_get_by_id_unset: > case op_get_by_id_direct: > case op_get_array_length: >+ case op_in_by_id: > case op_typeof: > case op_is_empty: > case op_is_undefined: >@@ -226,7 +227,7 @@ void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instructi > case op_enumerator_structure_pname: > case op_enumerator_generic_pname: > case op_get_by_val: >- case op_in: >+ case op_in_by_val: > case op_overrides_has_instance: > case op_instanceof: > case op_add: >@@ -454,7 +455,8 @@ void computeDefsForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instructi > case op_is_object_or_null: > case op_is_cell_with_type: > case op_is_function: >- case op_in: >+ case op_in_by_id: >+ case op_in_by_val: > case op_to_number: > case op_to_string: > case op_to_object: >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >index 8f1a4bd90e3cab0b5b02cfbf8611ade257933441..cce0b6a0069f42b58e19d8e9952fb1c3b4870555 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >@@ -589,7 +589,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink > break; > } > >- case op_in: >+ case op_in_by_val: > case op_put_by_val: > case op_put_by_val_direct: { > int arrayProfileIndex = pc[opLength - 1].u.operand; >diff --git a/Source/JavaScriptCore/bytecode/InlineAccess.cpp b/Source/JavaScriptCore/bytecode/InlineAccess.cpp >index 9130b1e25d44e6635817ea78a483ef8cad679790..f351f82bee0a4d794da90c5b86bc6dba59c3713c 100644 >--- a/Source/JavaScriptCore/bytecode/InlineAccess.cpp >+++ b/Source/JavaScriptCore/bytecode/InlineAccess.cpp >@@ -276,6 +276,25 @@ bool InlineAccess::generateArrayLength(StructureStubInfo& stubInfo, JSArray* arr > return linkedCodeInline; > } > >+bool InlineAccess::generateSelfInAccess(StructureStubInfo& stubInfo, Structure* structure) >+{ >+ CCallHelpers jit; >+ >+ GPRReg base = static_cast<GPRReg>(stubInfo.patch.baseGPR); >+ JSValueRegs value = stubInfo.valueRegs(); >+ >+ auto branchToSlowPath = jit.patchableBranch32( >+ MacroAssembler::NotEqual, >+ MacroAssembler::Address(base, JSCell::structureIDOffset()), >+ MacroAssembler::TrustedImm32(bitwise_cast<uint32_t>(structure->id()))); >+ jit.boxBooleanPayload(true, value.payloadGPR()); >+ >+ bool linkedCodeInline = linkCodeInline("in access", jit, stubInfo, [&] (LinkBuffer& linkBuffer) { >+ linkBuffer.link(branchToSlowPath, stubInfo.slowPathStartLocation()); >+ }); >+ return linkedCodeInline; >+} >+ > void InlineAccess::rewireStubAsJump(StructureStubInfo& stubInfo, CodeLocationLabel<JITStubRoutinePtrTag> target) > { > CCallHelpers jit; >diff --git a/Source/JavaScriptCore/bytecode/InlineAccess.h b/Source/JavaScriptCore/bytecode/InlineAccess.h >index 9948b3b6f85e936314cb1970c3ac4437ab8e68ba..a4d0335f8ab06607daa11bf1bf16b0e59b7f21ff 100644 >--- a/Source/JavaScriptCore/bytecode/InlineAccess.h >+++ b/Source/JavaScriptCore/bytecode/InlineAccess.h >@@ -116,6 +116,7 @@ class InlineAccess { > static bool isCacheableArrayLength(StructureStubInfo&, JSArray*); > static bool generateArrayLength(StructureStubInfo&, JSArray*); > static void rewireStubAsJump(StructureStubInfo&, CodeLocationLabel<JITStubRoutinePtrTag>); >+ static bool generateSelfInAccess(StructureStubInfo&, Structure*); > > // This is helpful when determining the size of an IC on > // various platforms. When adding a new type of IC, implement >diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp >index d5819aaa9af465704de1b4ad8169d9a367cc56b4..04218db047d09ced55bd372775a47c54167f99cc 100644 >--- a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp >+++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp >@@ -81,6 +81,15 @@ void StructureStubInfo::initPutByIdReplace(CodeBlock* codeBlock, Structure* base > u.byIdSelf.offset = offset; > } > >+void StructureStubInfo::initInByIdSelf(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset) >+{ >+ cacheType = CacheType::InByIdSelf; >+ >+ u.byIdSelf.baseObjectStructure.set( >+ *codeBlock->vm(), codeBlock, baseObjectStructure); >+ u.byIdSelf.offset = offset; >+} >+ > void StructureStubInfo::deref() > { > switch (cacheType) { >@@ -90,6 +99,7 @@ void StructureStubInfo::deref() > case CacheType::Unset: > case CacheType::GetByIdSelf: > case CacheType::PutByIdReplace: >+ case CacheType::InByIdSelf: > case CacheType::ArrayLength: > return; > } >@@ -106,6 +116,7 @@ void StructureStubInfo::aboutToDie() > case CacheType::Unset: > case CacheType::GetByIdSelf: > case CacheType::PutByIdReplace: >+ case CacheType::InByIdSelf: > case CacheType::ArrayLength: > return; > } >@@ -236,7 +247,7 @@ void StructureStubInfo::reset(CodeBlock* codeBlock) > resetPutByID(codeBlock, *this); > break; > case AccessType::In: >- resetIn(*this); >+ resetInByID(codeBlock, *this); > break; > case AccessType::InstanceOf: > resetInstanceOf(*this); >@@ -259,6 +270,7 @@ void StructureStubInfo::visitWeakReferences(CodeBlock* codeBlock) > switch (cacheType) { > case CacheType::GetByIdSelf: > case CacheType::PutByIdReplace: >+ case CacheType::InByIdSelf: > if (Heap::isMarked(u.byIdSelf.baseObjectStructure.get())) > return; > break; >@@ -282,6 +294,7 @@ bool StructureStubInfo::propagateTransitions(SlotVisitor& visitor) > return true; > case CacheType::GetByIdSelf: > case CacheType::PutByIdReplace: >+ case CacheType::InByIdSelf: > return u.byIdSelf.baseObjectStructure->markIfCheap(visitor); > case CacheType::Stub: > return u.stub->propagateTransitions(visitor); >diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h >index 14fed94ea1df6cc484171c79f098909c2cfd3f11..efe619b44951fb8f627ddb951f5ae8520621246a 100644 >--- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h >+++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h >@@ -58,6 +58,7 @@ enum class CacheType : int8_t { > Unset, > GetByIdSelf, > PutByIdReplace, >+ InByIdSelf, > Stub, > ArrayLength > }; >@@ -72,6 +73,7 @@ class StructureStubInfo { > void initGetByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset); > void initArrayLength(); > void initPutByIdReplace(CodeBlock*, Structure* baseObjectStructure, PropertyOffset); >+ void initInByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset); > > AccessGenerationResult addAccessCase(const GCSafeConcurrentJSLocker&, CodeBlock*, const Identifier&, std::unique_ptr<AccessCase>); > >@@ -174,7 +176,7 @@ class StructureStubInfo { > StructureSet bufferedStructures; > > struct { >- CodeLocationLabel<JITStubRoutinePtrTag> start; // This is either the start of the inline IC for *byId caches, or the location of patchable jump for 'in' and 'instanceof' caches. >+ CodeLocationLabel<JITStubRoutinePtrTag> start; // This is either the start of the inline IC for *byId caches. or the location of patchable jump for 'instanceof' caches. > RegisterSet usedRegisters; > uint32_t inlineSize; > int32_t deltaFromStartToSlowPathCallLocation; >@@ -195,7 +197,7 @@ class StructureStubInfo { > CodeLocationLabel<JITStubRoutinePtrTag> slowPathStartLocation() { return patch.start.labelAtOffset(patch.deltaFromStartToSlowPathStart); } > CodeLocationJump<JSInternalPtrTag> patchableJump() > { >- ASSERT(accessType == AccessType::In || accessType == AccessType::InstanceOf); >+ ASSERT(accessType == AccessType::InstanceOf); > return patch.start.jumpAtOffset<JSInternalPtrTag>(0); > } > >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 6d6449b30e278c3efae7082ee9e7005efd0b59b6..e199e8f1b41c1355366dc4884d53d6e333310549 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -2667,10 +2667,10 @@ RegisterID* BytecodeGenerator::emitInstanceOfCustom(RegisterID* dst, RegisterID* > return dst; > } > >-RegisterID* BytecodeGenerator::emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) >+RegisterID* BytecodeGenerator::emitInByVal(RegisterID* dst, RegisterID* property, RegisterID* base) > { > UnlinkedArrayProfile arrayProfile = newArrayProfile(); >- emitOpcode(op_in); >+ emitOpcode(op_in_by_val); > instructions().append(dst->index()); > instructions().append(base->index()); > instructions().append(property->index()); >@@ -2678,6 +2678,15 @@ RegisterID* BytecodeGenerator::emitIn(RegisterID* dst, RegisterID* property, Reg > return dst; > } > >+RegisterID* BytecodeGenerator::emitInById(RegisterID* dst, RegisterID* base, const Identifier& property) >+{ >+ emitOpcode(op_in_by_id); >+ instructions().append(dst->index()); >+ instructions().append(base->index()); >+ instructions().append(addConstant(property)); >+ return dst; >+} >+ > RegisterID* BytecodeGenerator::emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property) > { > ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties are not supported with tryGetById."); >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >index b7255ac6216e09dce1ad4d7c669ec546a2cb4673..97828ca50efa8b652ddff6e482993081da5ebc80 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >@@ -694,7 +694,8 @@ namespace JSC { > RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype); > RegisterID* emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue); > RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); } >- RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base); >+ RegisterID* emitInByVal(RegisterID* dst, RegisterID* property, RegisterID* base); >+ RegisterID* emitInById(RegisterID* dst, RegisterID* base, const Identifier& property); > > RegisterID* emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property); > RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property); >diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >index 07a9c907a7e2130a4244dfa0011f7ca52b06e8a6..a5fa525d216021b00d955ad9de63c11f336a58d1 100644 >--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >@@ -2280,10 +2280,16 @@ RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterI > > RegisterID* InNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) > { >+ if (isNonIndexStringElement(*m_expr1)) { >+ RefPtr<RegisterID> base = generator.emitNode(m_expr2); >+ generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); >+ return generator.emitInById(generator.finalDestination(dst, base.get()), base.get(), static_cast<StringNode*>(m_expr1)->value()); >+ } >+ > RefPtr<RegisterID> key = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); > RefPtr<RegisterID> base = generator.emitNode(m_expr2); > generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); >- return generator.emitIn(generator.finalDestination(dst, key.get()), key.get(), base.get()); >+ return generator.emitInByVal(generator.finalDestination(dst, key.get()), key.get(), base.get()); > } > > >diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >index 9bd8a533b1ce1d64c9323339c80f1475879f44c9..9da5f41c8db9d1f12cf3a3a311344771b0701024 100644 >--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >@@ -3259,10 +3259,30 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi > clobberWorld(); > break; > >- case In: { >+ case InById: { > // FIXME: We can determine when the property definitely exists based on abstract > // value information. > clobberWorld(); >+ filter(node->child1(), SpecObject); >+ setNonCellTypeForNode(node, SpecBoolean); >+ break; >+ } >+ >+ case InByVal: { >+ AbstractValue& property = forNode(node->child2()); >+ if (JSValue constant = property.value()) { >+ if (constant.isString()) { >+ JSString* string = asString(constant); >+ const StringImpl* impl = string->tryGetValueImpl(); >+ if (impl && impl->isAtomic()) >+ m_state.setFoundConstants(true); >+ } >+ } >+ >+ // FIXME: We can determine when the property definitely exists based on abstract >+ // value information. >+ clobberWorld(); >+ filter(node->child1(), SpecObject); > setNonCellTypeForNode(node, SpecBoolean); > break; > } >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index 3874fcc5b36dd94275ab253269550c132394e3d5..e0e7b43116a2c2f78dd459c77203ad7f0ec2b7d3 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -207,6 +207,8 @@ class ByteCodeParser { > void handlePutById( > Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus&, > bool isDirect); >+ void handleInById( >+ int destinationOperand, Node* base, unsigned identifierNumber, unsigned instructionSize); > > // Either register a watchpoint or emit a check for this condition. Returns false if the > // condition no longer holds, and therefore no reasonable check can be emitted. >@@ -4311,6 +4313,12 @@ void ByteCodeParser::handlePutById( > } } > } > >+void ByteCodeParser::handleInById(int destinationOperand, Node* base, unsigned identifierNumber, unsigned instructionSize) >+{ >+ UNUSED_PARAM(instructionSize); >+ set(VirtualRegister(destinationOperand), addToGraph(InById, OpInfo(identifierNumber), base)); >+} >+ > void ByteCodeParser::prepareToParseBlock() > { > clearCaches(); >@@ -6363,11 +6371,20 @@ void ByteCodeParser::parseBlock(unsigned limit) > NEXT_OPCODE(op_to_object); > } > >- case op_in: { >- ArrayMode arrayMode = getArrayMode(currentInstruction[OPCODE_LENGTH(op_in) - 1].u.arrayProfile); >+ case op_in_by_val: { >+ ArrayMode arrayMode = getArrayMode(currentInstruction[OPCODE_LENGTH(op_in_by_val) - 1].u.arrayProfile); > set(VirtualRegister(currentInstruction[1].u.operand), >- addToGraph(In, OpInfo(arrayMode.asWord()), get(VirtualRegister(currentInstruction[2].u.operand)), get(VirtualRegister(currentInstruction[3].u.operand)))); >- NEXT_OPCODE(op_in); >+ addToGraph(InByVal, OpInfo(arrayMode.asWord()), get(VirtualRegister(currentInstruction[2].u.operand)), get(VirtualRegister(currentInstruction[3].u.operand)))); >+ NEXT_OPCODE(op_in_by_val); >+ } >+ >+ case op_in_by_id: { >+ Node* base = get(VirtualRegister(currentInstruction[2].u.operand)); >+ unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand]; >+ unsigned opcodeLength = OPCODE_LENGTH(op_in_by_id); >+ handleInById(currentInstruction[1].u.operand, base, identifierNumber, opcodeLength); >+ NEXT_OPCODE(op_in_by_id); >+ break; > } > > case op_get_enumerable_length: { >diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >index 5cee65b6843eca5088ed1a9a91094f34057aaa44..dadc92d867e4c44a3462d8d6dab6458075acdd75 100644 >--- a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >@@ -236,7 +236,8 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc > case op_to_object: > case op_switch_imm: > case op_switch_char: >- case op_in: >+ case op_in_by_val: >+ case op_in_by_id: > case op_get_scope: > case op_get_from_scope: > case op_get_enumerable_length: >diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h >index ad623647a77040c0d3b826cdc1a370c1a23b9bdc..552edefae52b89899806187ea91d27175dfc658e 100644 >--- a/Source/JavaScriptCore/dfg/DFGClobberize.h >+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h >@@ -619,7 +619,8 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu > case ConstructVarargs: > case ConstructForwardVarargs: > case ToPrimitive: >- case In: >+ case InByVal: >+ case InById: > case HasOwnProperty: > case ValueAdd: > case SetFunctionName: >diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >index 7374185667e0bdb787a83b702cb18959b5069d01..b7edc060f436293aca4988833ea94620c572ca0d 100644 >--- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >@@ -616,6 +616,23 @@ class ConstantFoldingPhase : public Phase { > break; > } > >+ case InByVal: { >+ AbstractValue& property = m_state.forNode(node->child2()); >+ if (JSValue constant = property.value()) { >+ if (constant.isString()) { >+ JSString* string = asString(constant); >+ const StringImpl* impl = string->tryGetValueImpl(); >+ if (impl && impl->isAtomic()) { >+ unsigned identifierNumber = m_graph.identifiers().ensure(const_cast<UniquedStringImpl*>(static_cast<const UniquedStringImpl*>(impl))); >+ node->convertToInById(identifierNumber); >+ changed = true; >+ break; >+ } >+ } >+ } >+ break; >+ } >+ > case ToPrimitive: { > if (m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol | SpecBigInt)) > break; >diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >index 974d971366ffd8b79786fbb26ded3ac25b687fda..416210a90cefb0d83d90b1549a1fec027cd95e51 100644 >--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >@@ -193,7 +193,8 @@ bool doesGC(Graph& graph, Node* node) > case CallStringConstructor: > case NumberToStringWithRadix: > case NumberToStringWithValidRadixConstant: >- case In: >+ case InByVal: >+ case InById: > case HasOwnProperty: > case Jump: > case Branch: >diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >index 0101d379bcd6f745e72a88ec219fbcf329e38a9b..9a1dc136d016edaa2af0a360eed7bf3e20673aa0 100644 >--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >@@ -1469,7 +1469,12 @@ class FixupPhase : public Phase { > fixEdge<CellUse>(node->child2()); > break; > >- case In: { >+ case InById: { >+ fixEdge<CellUse>(node->child1()); >+ break; >+ } >+ >+ case InByVal: { > if (node->child2()->shouldSpeculateInt32()) { > convertToHasIndexedProperty(node); > break; >diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp >index 5e5a7a875244241b526a9f24b4ff40ce9885bf61..5fd50b8c7f01ee36e1b273aac23a0c8622783ac4 100644 >--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp >+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp >@@ -265,26 +265,9 @@ void JITCompiler::link(LinkBuffer& linkBuffer) > finalizeInlineCaches(m_getByIds, linkBuffer); > finalizeInlineCaches(m_getByIdsWithThis, linkBuffer); > finalizeInlineCaches(m_putByIds, linkBuffer); >+ finalizeInlineCaches(m_inByIds, linkBuffer); > finalizeInlineCaches(m_instanceOfs, linkBuffer); > >- for (unsigned i = 0; i < m_ins.size(); ++i) { >- StructureStubInfo& info = *m_ins[i].m_stubInfo; >- >- CodeLocationLabel<JITStubRoutinePtrTag> start = linkBuffer.locationOf<JITStubRoutinePtrTag>(m_ins[i].m_jump); >- info.patch.start = start; >- >- ptrdiff_t inlineSize = MacroAssembler::differenceBetweenCodePtr( >- start, linkBuffer.locationOf<JSInternalPtrTag>(m_ins[i].m_done)); >- RELEASE_ASSERT(inlineSize >= 0); >- info.patch.inlineSize = inlineSize; >- >- info.patch.deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr( >- start, linkBuffer.locationOf<JSInternalPtrTag>(m_ins[i].m_slowPathGenerator->call())); >- >- info.patch.deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr( >- start, linkBuffer.locationOf<JSInternalPtrTag>(m_ins[i].m_slowPathGenerator->label())); >- } >- > auto linkCallThunk = FunctionPtr<NoPtrTag>(vm()->getCTIStub(linkCallThunkGenerator).retaggedCode<NoPtrTag>()); > for (auto& record : m_jsCalls) { > CallLinkInfo& info = *record.info; >diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h >index 050eb7c16f6db904489bd2b786cd3fd1f029459e..c17b03211488bf859be55504e2eab0adfa434988 100644 >--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h >+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h >@@ -76,23 +76,6 @@ struct CallLinkRecord { > FunctionPtr<OperationPtrTag> m_function; > }; > >-struct InRecord { >- InRecord( >- MacroAssembler::PatchableJump jump, MacroAssembler::Label done, >- SlowPathGenerator* slowPathGenerator, StructureStubInfo* stubInfo) >- : m_jump(jump) >- , m_done(done) >- , m_slowPathGenerator(slowPathGenerator) >- , m_stubInfo(stubInfo) >- { >- } >- >- MacroAssembler::PatchableJump m_jump; >- MacroAssembler::Label m_done; >- SlowPathGenerator* m_slowPathGenerator; >- StructureStubInfo* m_stubInfo; >-}; >- > // === JITCompiler === > // > // DFG::JITCompiler is responsible for generating JIT code from the dataflow graph. >@@ -209,11 +192,11 @@ class JITCompiler : public CCallHelpers { > m_instanceOfs.append(InlineCacheWrapper<JITInstanceOfGenerator>(gen, slowPath)); > } > >- void addIn(const InRecord& record) >+ void addInById(const JITInByIdGenerator& gen, SlowPathGenerator* slowPath) > { >- m_ins.append(record); >+ m_inByIds.append(InlineCacheWrapper<JITInByIdGenerator>(gen, slowPath)); > } >- >+ > void addJSCall(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo* info) > { > m_jsCalls.append(JSCallRecord(fastCall, slowCall, targetToCheck, info)); >@@ -359,8 +342,8 @@ class JITCompiler : public CCallHelpers { > Vector<InlineCacheWrapper<JITGetByIdGenerator>, 4> m_getByIds; > Vector<InlineCacheWrapper<JITGetByIdWithThisGenerator>, 4> m_getByIdsWithThis; > Vector<InlineCacheWrapper<JITPutByIdGenerator>, 4> m_putByIds; >+ Vector<InlineCacheWrapper<JITInByIdGenerator>, 4> m_inByIds; > Vector<InlineCacheWrapper<JITInstanceOfGenerator>, 4> m_instanceOfs; >- Vector<InRecord, 4> m_ins; > Vector<JSCallRecord, 4> m_jsCalls; > Vector<JSDirectCallRecord, 4> m_jsDirectCalls; > Vector<JSDirectTailCallRecord, 4> m_jsDirectTailCalls; >diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h >index 4d97cd3ab127d30bbf46ac739edbf1bea85c130d..f6e10eb3db322acd0c3ac4555b9d5cb4eda98814 100644 >--- a/Source/JavaScriptCore/dfg/DFGNode.h >+++ b/Source/JavaScriptCore/dfg/DFGNode.h >@@ -743,6 +743,15 @@ struct Node { > setOp(SetRegExpObjectLastIndex); > m_opInfo = false; > } >+ >+ void convertToInById(unsigned identifierNumber) >+ { >+ ASSERT(m_op == InByVal); >+ setOpAndDefaultFlags(InById); >+ children.setChild2(Edge()); >+ m_opInfo = identifierNumber; >+ m_opInfo2 = OpInfoWrapper(); >+ } > > JSValue asJSValue() > { >@@ -1010,6 +1019,7 @@ struct Node { > case PutSetterById: > case PutGetterSetterById: > case DeleteById: >+ case InById: > case GetDynamicVar: > case PutDynamicVar: > case ResolveScopeForHoistingFuncDeclInEval: >@@ -1967,7 +1977,7 @@ struct Node { > case GetIndexedPropertyStorage: > case GetArrayLength: > case GetVectorLength: >- case In: >+ case InByVal: > case PutByValDirect: > case PutByVal: > case PutByValAlias: >diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h >index feec25e57c3bbdda49a0911caa81887e7ec40b1e..4fba90da757d86e1616da352260f8ebc373dfa60 100644 >--- a/Source/JavaScriptCore/dfg/DFGNodeType.h >+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h >@@ -369,7 +369,8 @@ namespace JSC { namespace DFG { > macro(NumberToStringWithValidRadixConstant, NodeResultJS) \ > macro(NewStringObject, NodeResultJS) \ > macro(MakeRope, NodeResultJS) \ >- macro(In, NodeResultBoolean | NodeMustGenerate) \ >+ macro(InByVal, NodeResultBoolean | NodeMustGenerate) \ >+ macro(InById, NodeResultBoolean | NodeMustGenerate) \ > macro(ProfileType, NodeMustGenerate) \ > macro(ProfileControlFlow, NodeMustGenerate) \ > macro(SetFunctionName, NodeMustGenerate) \ >diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >index 4bcb02c6085ca100685f3f5917f3855f1a1cb431..228643b207a31587466f2f07300fa3015b987978 100644 >--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >@@ -980,7 +980,8 @@ class PredictionPropagationPhase : public Phase { > setPrediction(SpecObjectOther); > break; > >- case In: >+ case InByVal: >+ case InById: > setPrediction(SpecBoolean); > break; > >diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >index f183ae949e4457e6b394b61d8e4f47f326d49e9c..82eed6a68dad8c53c1f7b61d38d4d2a3c87cb661 100644 >--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >@@ -332,7 +332,8 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node) > case CallStringConstructor: > case NewStringObject: > case MakeRope: >- case In: >+ case InByVal: >+ case InById: > case HasOwnProperty: > case PushWithScope: > case CreateActivation: >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >index 3f934e3b11d81c8fbbb221b767e01a340452c1ca..a582f2f26a59ed3d49df2bcfd8e8c6672fd5397b 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >@@ -1056,67 +1056,52 @@ void SpeculativeJIT::compileGetByIdFlush(Node* node, AccessType accessType) > } > } > >-void SpeculativeJIT::compileIn(Node* node) >+void SpeculativeJIT::compileInById(Node* node) > { > SpeculateCellOperand base(this, node->child1()); >+ JSValueRegsTemporary result(this, Reuse, base); >+ > GPRReg baseGPR = base.gpr(); >- >- if (JSString* string = node->child2()->dynamicCastConstant<JSString*>(*m_jit.vm())) { >- if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) { >- StructureStubInfo* stubInfo = m_jit.codeBlock()->addStubInfo(AccessType::In); >- >- GPRTemporary result(this); >- GPRReg resultGPR = result.gpr(); >+ JSValueRegs resultRegs = result.regs(); > >- use(node->child2()); >- >- MacroAssembler::PatchableJump jump = m_jit.patchableJump(); >- MacroAssembler::Label done = m_jit.label(); >- >- // Since this block is executed only when the result of string->tryGetValueImpl() is atomic, >- // we can cast it to const AtomicStringImpl* safely. >- auto slowPath = slowPathCall( >- jump.m_jump, this, operationInOptimize, >- JSValueRegs::payloadOnly(resultGPR), stubInfo, baseGPR, >- static_cast<const AtomicStringImpl*>(string->tryGetValueImpl())); >- >- stubInfo->callSiteIndex = m_jit.addCallSite(node->origin.semantic); >- stubInfo->codeOrigin = node->origin.semantic; >- stubInfo->patch.baseGPR = static_cast<int8_t>(baseGPR); >- stubInfo->patch.valueGPR = static_cast<int8_t>(resultGPR); >- stubInfo->patch.thisGPR = static_cast<int8_t>(InvalidGPRReg); >-#if USE(JSVALUE32_64) >- stubInfo->patch.valueTagGPR = static_cast<int8_t>(InvalidGPRReg); >- stubInfo->patch.baseTagGPR = static_cast<int8_t>(InvalidGPRReg); >- stubInfo->patch.thisTagGPR = static_cast<int8_t>(InvalidGPRReg); >-#endif >- stubInfo->patch.usedRegisters = usedRegisters(); >+ base.use(); > >- m_jit.addIn(InRecord(jump, done, slowPath.get(), stubInfo)); >- addSlowPathGenerator(WTFMove(slowPath)); >+ CodeOrigin codeOrigin = node->origin.semantic; >+ CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size()); >+ RegisterSet usedRegisters = this->usedRegisters(); >+ JITInByIdGenerator gen( >+ m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(node->identifierNumber()), >+ JSValueRegs(baseGPR), resultRegs); >+ gen.generateFastPath(m_jit); > >- base.use(); >+ auto slowPath = slowPathCall( >+ gen.slowPathJump(), this, operationInByIdOptimize, >+ NeedToSpill, ExceptionCheckRequirement::CheckNeeded, >+ resultRegs, gen.stubInfo(), baseGPR, identifierUID(node->identifierNumber())); > >- blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly); >- return; >- } >- } >+ m_jit.addInById(gen, slowPath.get()); >+ addSlowPathGenerator(WTFMove(slowPath)); > >+ blessedBooleanResult(resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly); >+} >+ >+void SpeculativeJIT::compileInByVal(Node* node) >+{ >+ SpeculateCellOperand base(this, node->child1()); > JSValueOperand key(this, node->child2()); >+ >+ GPRReg baseGPR = base.gpr(); > JSValueRegs regs = key.jsValueRegs(); >- >- GPRFlushedCallResult result(this); >- GPRReg resultGPR = result.gpr(); >- >+ > base.use(); > key.use(); >- >+ > flushRegisters(); >- callOperation( >- operationGenericIn, extractResult(JSValueRegs::payloadOnly(resultGPR)), >- baseGPR, regs); >+ JSValueRegsFlushedCallResult result(this); >+ JSValueRegs resultRegs = result.regs(); >+ callOperation(operationInByVal, resultRegs, baseGPR, regs); > m_jit.exceptionCheck(); >- blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly); >+ blessedBooleanResult(resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly); > } > > void SpeculativeJIT::compileDeleteById(Node* node) >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >index 0b7912dccc25c34cec5eda47425e9644f5baf777..46174c94a49e3c78e8a55a8b83bbb0428bae3361 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >@@ -735,7 +735,8 @@ class SpeculativeJIT { > void compilePushWithScope(Node*); > void compileGetById(Node*, AccessType); > void compileGetByIdFlush(Node*, AccessType); >- void compileIn(Node*); >+ void compileInById(Node*); >+ void compileInByVal(Node*); > > void nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand); > void nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode); >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >index 9f131d914b1e5002b5466c174a7878e6a67534e2..3efb7b7e45081e68e5ad8a0e4c5bdb2a418ad36b 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >@@ -3751,8 +3751,12 @@ void SpeculativeJIT::compile(Node* node) > compileSetFunctionName(node); > break; > >- case In: >- compileIn(node); >+ case InById: >+ compileInById(node); >+ break; >+ >+ case InByVal: >+ compileInByVal(node); > break; > > case HasOwnProperty: { >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >index a2caa003afbd6ffa7bcde182e40a277fc32264aa..8d386977ca83b2468984911a36f2a9a914258899 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >@@ -4301,8 +4301,12 @@ void SpeculativeJIT::compile(Node* node) > compileSetFunctionName(node); > break; > >- case In: >- compileIn(node); >+ case InById: >+ compileInById(node); >+ break; >+ >+ case InByVal: >+ compileInByVal(node); > break; > > case HasOwnProperty: { >diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >index 06863d0e22d64e6a1b13373bb13b0b743a5cc2ed..6b951348ed242b4bd02673737fc5d4b176997654 100644 >--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >@@ -205,7 +205,8 @@ inline CapabilityLevel canCompile(Node* node) > case Throw: > case ThrowStaticError: > case Unreachable: >- case In: >+ case InByVal: >+ case InById: > case HasOwnProperty: > case IsCellWithType: > case MapHash: >diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >index 12c93386afa5ff33c83a7a6077500b2aba3b9267..720f7758dc6414389db793663e026e87a2595a42 100644 >--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >@@ -708,8 +708,11 @@ class LowerDFGToB3 { > case GetByIdDirectFlush: > compileGetById(AccessType::GetDirect); > break; >- case In: >- compileIn(); >+ case InById: >+ compileInById(); >+ break; >+ case InByVal: >+ compileInByVal(); > break; > case HasOwnProperty: > compileHasOwnProperty(); >@@ -9669,87 +9672,70 @@ class LowerDFGToB3 { > setJSValue(m_out.phi(Int64, results)); > } > >- void compileIn() >+ void compileInByVal() > { >- DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == CellUse, m_node->child1().useKind()); >+ setJSValue(m_out.notZero64(vmCall(Int64, m_out.operation(operationInByVal), m_callFrame, lowCell(m_node->child1()), lowJSValue(m_node->child2())))); >+ } > >+ void compileInById() >+ { > Node* node = m_node; >- Edge base = node->child1(); >- LValue cell = lowCell(base); >- if (JSString* string = node->child2()->dynamicCastConstant<JSString*>(vm())) { >- if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) { >- UniquedStringImpl* str = bitwise_cast<UniquedStringImpl*>(string->tryGetValueImpl()); >- PatchpointValue* patchpoint = m_out.patchpoint(Int64); >- patchpoint->appendSomeRegister(cell); >- patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); >- patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); >- patchpoint->clobber(RegisterSet::macroScratchRegisters()); >- >- RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint); >- >- State* state = &m_ftlState; >- patchpoint->setGenerator( >- [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()]; >+ LValue base = lowCell(m_node->child1()); >+ >+ PatchpointValue* patchpoint = m_out.patchpoint(Int64); >+ patchpoint->appendSomeRegister(base); >+ patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); >+ patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); >+ >+ patchpoint->clobber(RegisterSet::macroScratchRegisters()); >+ >+ RefPtr<PatchpointExceptionHandle> exceptionHandle = >+ preparePatchpointForExceptions(patchpoint); >+ >+ State* state = &m_ftlState; >+ patchpoint->setGenerator( >+ [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ AllowMacroScratchRegisterUsage allowScratch(jit); >+ >+ CallSiteIndex callSiteIndex = >+ state->jitCode->common.addUniqueCallSiteIndex(node->origin.semantic); >+ >+ // This is the direct exit target for operation calls. >+ Box<CCallHelpers::JumpList> exceptions = >+ exceptionHandle->scheduleExitCreation(params)->jumps(jit); >+ >+ auto generator = Box<JITInByIdGenerator>::create( >+ jit.codeBlock(), node->origin.semantic, callSiteIndex, >+ params.unavailableRegisters(), uid, JSValueRegs(params[1].gpr()), >+ JSValueRegs(params[0].gpr())); >+ >+ generator->generateFastPath(jit); >+ CCallHelpers::Label done = jit.label(); >+ >+ params.addLatePath( >+ [=] (CCallHelpers& jit) { > AllowMacroScratchRegisterUsage allowScratch(jit); > >- // This is the direct exit target for operation calls. We don't need a JS exceptionHandle because we don't >- // cache Proxy objects. >- Box<CCallHelpers::JumpList> exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit); >- >- GPRReg baseGPR = params[1].gpr(); >- GPRReg resultGPR = params[0].gpr(); >- >- StructureStubInfo* stubInfo = >- jit.codeBlock()->addStubInfo(AccessType::In); >- stubInfo->callSiteIndex = >- state->jitCode->common.addCodeOrigin(node->origin.semantic); >- stubInfo->codeOrigin = node->origin.semantic; >- stubInfo->patch.baseGPR = static_cast<int8_t>(baseGPR); >- stubInfo->patch.valueGPR = static_cast<int8_t>(resultGPR); >- stubInfo->patch.thisGPR = static_cast<int8_t>(InvalidGPRReg); >- stubInfo->patch.usedRegisters = params.unavailableRegisters(); >- >- CCallHelpers::PatchableJump jump = jit.patchableJump(); >- CCallHelpers::Label done = jit.label(); >- >- params.addLatePath( >- [=] (CCallHelpers& jit) { >- AllowMacroScratchRegisterUsage allowScratch(jit); >- >- jump.m_jump.link(&jit); >- CCallHelpers::Label slowPathBegin = jit.label(); >- CCallHelpers::Call slowPathCall = callOperation( >- *state, params.unavailableRegisters(), jit, >- node->origin.semantic, exceptions.get(), operationInOptimize, >- resultGPR, CCallHelpers::TrustedImmPtr(stubInfo), baseGPR, >- CCallHelpers::TrustedImmPtr(str)).call(); >- jit.jump().linkTo(done, &jit); >- >- jit.addLinkTask( >- [=] (LinkBuffer& linkBuffer) { >- CodeLocationLabel<JITStubRoutinePtrTag> start = linkBuffer.locationOf<JITStubRoutinePtrTag>(jump); >- stubInfo->patch.start = start; >- ptrdiff_t inlineSize = MacroAssembler::differenceBetweenCodePtr( >- start, linkBuffer.locationOf<NoPtrTag>(done)); >- RELEASE_ASSERT(inlineSize >= 0); >- stubInfo->patch.inlineSize = inlineSize; >- >- stubInfo->patch.deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr( >- start, linkBuffer.locationOf<NoPtrTag>(slowPathCall)); >- >- stubInfo->patch.deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr( >- start, linkBuffer.locationOf<NoPtrTag>(slowPathBegin)); >- >- }); >+ generator->slowPathJump().link(&jit); >+ CCallHelpers::Label slowPathBegin = jit.label(); >+ CCallHelpers::Call slowPathCall = callOperation( >+ *state, params.unavailableRegisters(), jit, node->origin.semantic, >+ exceptions.get(), operationInByIdOptimize, params[0].gpr(), >+ CCallHelpers::TrustedImmPtr(generator->stubInfo()), params[1].gpr(), >+ CCallHelpers::TrustedImmPtr(uid)).call(); >+ jit.jump().linkTo(done, &jit); >+ >+ generator->reportSlowPathCall(slowPathBegin, slowPathCall); >+ >+ jit.addLinkTask( >+ [=] (LinkBuffer& linkBuffer) { >+ generator->finalize(linkBuffer, linkBuffer); > }); > }); >+ }); > >- setJSValue(patchpoint); >- return; >- } >- } >- >- setJSValue(vmCall(Int64, m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child2()))); >+ setJSValue(patchpoint); > } > > void compileHasOwnProperty() >diff --git a/Source/JavaScriptCore/jit/ICStats.h b/Source/JavaScriptCore/jit/ICStats.h >index c1c2d4e957dfeae712039c45cbe7b95c62a825c0..684e813dc4a4a83c6751030e0bc7b66b9bf2a199 100644 >--- a/Source/JavaScriptCore/jit/ICStats.h >+++ b/Source/JavaScriptCore/jit/ICStats.h >@@ -50,9 +50,10 @@ namespace JSC { > macro(OperationGetByIdBuildList) \ > macro(OperationGetByIdOptimize) \ > macro(OperationGetByIdWithThisOptimize) \ >- macro(OperationInOptimize) \ >- macro(OperationIn) \ > macro(OperationGenericIn) \ >+ macro(OperationInById) \ >+ macro(OperationInByIdGeneric) \ >+ macro(OperationInByIdOptimize) \ > macro(OperationPutByIdStrict) \ > macro(OperationPutByIdNonStrict) \ > macro(OperationPutByIdDirectStrict) \ >@@ -67,7 +68,8 @@ namespace JSC { > macro(OperationPutByIdDirectNonStrictBuildList) \ > macro(PutByIdAddAccessCase) \ > macro(PutByIdReplaceWithJump) \ >- macro(PutByIdSelfPatch) >+ macro(PutByIdSelfPatch) \ >+ macro(InByIdSelfPatch) > > class ICEvent { > public: >diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp >index 199d81a8a35a34b312ef3156f2fd8d3464737dbe..d9db0629a438c129d57bfa3831669eb8af156998 100644 >--- a/Source/JavaScriptCore/jit/JIT.cpp >+++ b/Source/JavaScriptCore/jit/JIT.cpp >@@ -78,11 +78,6 @@ JIT::JIT(VM* vm, CodeBlock* codeBlock, unsigned loopOSREntryBytecodeOffset) > , m_interpreter(vm->interpreter) > , m_labels(codeBlock ? codeBlock->numberOfInstructions() : 0) > , m_bytecodeOffset(std::numeric_limits<unsigned>::max()) >- , m_getByIdIndex(UINT_MAX) >- , m_getByIdWithThisIndex(UINT_MAX) >- , m_putByIdIndex(UINT_MAX) >- , m_byValInstructionIndex(UINT_MAX) >- , m_callLinkInfoIndex(UINT_MAX) > , m_pcToCodeOriginMapBuilder(*vm) > , m_canBeOptimized(false) > , m_shouldEmitProfiling(false) >@@ -277,7 +272,7 @@ void JIT::privateCompileMainPass() > unsigned bytecodeOffset = m_bytecodeOffset; > > switch (opcodeID) { >- DEFINE_SLOW_OP(in) >+ DEFINE_SLOW_OP(in_by_val) > DEFINE_SLOW_OP(less) > DEFINE_SLOW_OP(lesseq) > DEFINE_SLOW_OP(greater) >@@ -341,6 +336,7 @@ void JIT::privateCompileMainPass() > DEFINE_OP(op_below) > DEFINE_OP(op_beloweq) > DEFINE_OP(op_try_get_by_id) >+ DEFINE_OP(op_in_by_id) > case op_get_array_length: > case op_get_by_id_proto_load: > case op_get_by_id_unset: >@@ -478,6 +474,7 @@ void JIT::privateCompileSlowCases() > m_getByIdIndex = 0; > m_getByIdWithThisIndex = 0; > m_putByIdIndex = 0; >+ m_inByIdIndex = 0; > m_instanceOfIndex = 0; > m_byValInstructionIndex = 0; > m_callLinkInfoIndex = 0; >@@ -521,6 +518,7 @@ void JIT::privateCompileSlowCases() > DEFINE_SLOWCASE_OP(op_construct) > DEFINE_SLOWCASE_OP(op_eq) > DEFINE_SLOWCASE_OP(op_try_get_by_id) >+ DEFINE_SLOWCASE_OP(op_in_by_id) > case op_get_array_length: > case op_get_by_id_proto_load: > case op_get_by_id_unset: >@@ -600,6 +598,7 @@ void JIT::privateCompileSlowCases() > RELEASE_ASSERT(m_getByIdIndex == m_getByIds.size()); > RELEASE_ASSERT(m_getByIdWithThisIndex == m_getByIdsWithThis.size()); > RELEASE_ASSERT(m_putByIdIndex == m_putByIds.size()); >+ RELEASE_ASSERT(m_inByIdIndex == m_inByIds.size()); > RELEASE_ASSERT(m_instanceOfIndex == m_instanceOfs.size()); > RELEASE_ASSERT(m_callLinkInfoIndex == m_callCompilationInfo.size()); > RELEASE_ASSERT(numberOfValueProfiles == m_codeBlock->numberOfValueProfiles()); >@@ -842,6 +841,7 @@ CompilationResult JIT::link() > finalizeInlineCaches(m_getByIds, patchBuffer); > finalizeInlineCaches(m_getByIdsWithThis, patchBuffer); > finalizeInlineCaches(m_putByIds, patchBuffer); >+ finalizeInlineCaches(m_inByIds, patchBuffer); > finalizeInlineCaches(m_instanceOfs, patchBuffer); > > if (m_byValCompilationInfo.size()) { >diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h >index 156f1b58129f7f6cf76f1395a53a9a9d208dbfd4..b96aa22433aabda50ea8da9f3a995d904b797957 100644 >--- a/Source/JavaScriptCore/jit/JIT.h >+++ b/Source/JavaScriptCore/jit/JIT.h >@@ -500,6 +500,7 @@ namespace JSC { > void emit_op_get_arguments_length(Instruction*); > void emit_op_get_by_val(Instruction*); > void emit_op_get_argument_by_val(Instruction*); >+ void emit_op_in_by_id(Instruction*); > void emit_op_init_lazy_reg(Instruction*); > void emit_op_overrides_has_instance(Instruction*); > void emit_op_instanceof(Instruction*); >@@ -611,6 +612,7 @@ namespace JSC { > void emitSlow_op_get_arguments_length(Instruction*, Vector<SlowCaseEntry>::iterator&); > void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); > void emitSlow_op_get_argument_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); >+ void emitSlow_op_in_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&); > void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&); > void emitSlow_op_instanceof_custom(Instruction*, Vector<SlowCaseEntry>::iterator&); > void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&); >@@ -865,6 +867,7 @@ namespace JSC { > Vector<JITGetByIdGenerator> m_getByIds; > Vector<JITGetByIdWithThisGenerator> m_getByIdsWithThis; > Vector<JITPutByIdGenerator> m_putByIds; >+ Vector<JITInByIdGenerator> m_inByIds; > Vector<JITInstanceOfGenerator> m_instanceOfs; > Vector<ByValCompilationInfo> m_byValCompilationInfo; > Vector<CallCompilationInfo> m_callCompilationInfo; >@@ -878,12 +881,13 @@ namespace JSC { > JumpList m_exceptionChecksWithCallFrameRollback; > Label m_exceptionHandler; > >- unsigned m_getByIdIndex; >- unsigned m_getByIdWithThisIndex; >- unsigned m_putByIdIndex; >- unsigned m_instanceOfIndex; >- unsigned m_byValInstructionIndex; >- unsigned m_callLinkInfoIndex; >+ unsigned m_getByIdIndex { UINT_MAX }; >+ unsigned m_getByIdWithThisIndex { UINT_MAX }; >+ unsigned m_putByIdIndex { UINT_MAX }; >+ unsigned m_inByIdIndex { UINT_MAX }; >+ unsigned m_instanceOfIndex { UINT_MAX }; >+ unsigned m_byValInstructionIndex { UINT_MAX }; >+ unsigned m_callLinkInfoIndex { UINT_MAX }; > > Label m_arityCheck; > std::unique_ptr<LinkBuffer> m_linkBuffer; >diff --git a/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp b/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp >index 8f17e9e7a39dd6ad086c01a34e2c18084b923f14..9daf49dbe93ebd16a89762abf607ed04221dc9d8 100644 >--- a/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp >+++ b/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp >@@ -166,6 +166,20 @@ V_JITOperation_ESsiJJI JITPutByIdGenerator::slowPathFunction() > return operationPutByIdNonStrictOptimize; > } > >+JITInByIdGenerator::JITInByIdGenerator( >+ CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet& usedRegisters, >+ UniquedStringImpl* propertyName, JSValueRegs base, JSValueRegs value) >+ : JITByIdGenerator(codeBlock, codeOrigin, callSite, AccessType::In, usedRegisters, base, value) >+ , m_isLengthAccess(propertyName == codeBlock->vm()->propertyNames->length.impl()) >+{ >+ RELEASE_ASSERT(base.payloadGPR() != value.tagGPR()); >+} >+ >+void JITInByIdGenerator::generateFastPath(MacroAssembler& jit) >+{ >+ generateFastCommon(jit, m_isLengthAccess ? InlineAccess::sizeForLengthAccess() : InlineAccess::sizeForPropertyAccess()); >+} >+ > JITInstanceOfGenerator::JITInstanceOfGenerator( > CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, > const RegisterSet& usedRegisters, GPRReg result, GPRReg value, GPRReg prototype, >diff --git a/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h b/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h >index 07a08c85c23c22305c3aa45cf4537bd9c765b404..1a524d8e62c26c872202b3fb2a2d9d9e6b2a60dc 100644 >--- a/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h >+++ b/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h >@@ -143,6 +143,20 @@ class JITPutByIdGenerator : public JITByIdGenerator { > PutKind m_putKind; > }; > >+class JITInByIdGenerator : public JITByIdGenerator { >+public: >+ JITInByIdGenerator() { } >+ >+ JITInByIdGenerator( >+ CodeBlock*, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, UniquedStringImpl* propertyName, >+ JSValueRegs base, JSValueRegs value); >+ >+ void generateFastPath(MacroAssembler&); >+ >+private: >+ bool m_isLengthAccess; >+}; >+ > class JITInstanceOfGenerator : public JITInlineCacheGenerator { > public: > JITInstanceOfGenerator() { } >diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp >index bf1677e22c73e24641cbe8e0e39e55064097be11..76d72e29739b601053ef5230a7dd000b66efa4e1 100644 >--- a/Source/JavaScriptCore/jit/JITOperations.cpp >+++ b/Source/JavaScriptCore/jit/JITOperations.cpp >@@ -377,64 +377,88 @@ EncodedJSValue JIT_OPERATION operationGetByIdWithThisOptimize(ExecState* exec, S > })); > } > >-EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key) >+EncodedJSValue JIT_OPERATION operationInById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid) > { > SuperSamplerScope superSamplerScope(false); >- >- VM* vm = &exec->vm(); >- NativeCallFrameTracer tracer(vm, exec); >- auto scope = DECLARE_THROW_SCOPE(*vm); > >- if (!base->isObject()) { >- throwException(exec, scope, createInvalidInParameterError(exec, base)); >+ VM& vm = exec->vm(); >+ NativeCallFrameTracer tracer(&vm, exec); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ stubInfo->tookSlowPath = true; >+ >+ Identifier ident = Identifier::fromUid(&vm, uid); >+ >+ JSValue baseValue = JSValue::decode(base); >+ if (!baseValue.isObject()) { >+ throwException(exec, scope, createInvalidInParameterError(exec, baseValue)); > return JSValue::encode(jsUndefined()); > } >- >- AccessType accessType = static_cast<AccessType>(stubInfo->accessType); >+ JSObject* baseObject = asObject(baseValue); > >- Identifier ident = Identifier::fromUid(vm, key); >- LOG_IC((ICEvent::OperationInOptimize, base->classInfo(*vm), ident)); >- PropertySlot slot(base, PropertySlot::InternalMethodType::HasProperty); >- bool result = asObject(base)->getPropertySlot(exec, ident, slot); >- RETURN_IF_EXCEPTION(scope, encodedJSValue()); >- >- RELEASE_ASSERT(accessType == stubInfo->accessType); >- >- if (stubInfo->considerCaching(exec->codeBlock(), asObject(base)->structure())) >- repatchIn(exec, base, ident, result, slot, *stubInfo); >- >- return JSValue::encode(jsBoolean(result)); >+ LOG_IC((ICEvent::OperationInById, baseObject->classInfo(vm), ident)); >+ >+ PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty); >+ return JSValue::encode(jsBoolean(baseObject->getPropertySlot(exec, ident, slot))); > } > >-EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key) >+EncodedJSValue JIT_OPERATION operationInByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid) > { > SuperSamplerScope superSamplerScope(false); >- >- VM* vm = &exec->vm(); >- NativeCallFrameTracer tracer(vm, exec); >- auto scope = DECLARE_THROW_SCOPE(*vm); > >- stubInfo->tookSlowPath = true; >+ VM& vm = exec->vm(); >+ NativeCallFrameTracer tracer(&vm, exec); >+ auto scope = DECLARE_THROW_SCOPE(vm); > >- if (!base->isObject()) { >- throwException(exec, scope, createInvalidInParameterError(exec, base)); >+ Identifier ident = Identifier::fromUid(&vm, uid); >+ >+ JSValue baseValue = JSValue::decode(base); >+ if (!baseValue.isObject()) { >+ throwException(exec, scope, createInvalidInParameterError(exec, baseValue)); > return JSValue::encode(jsUndefined()); > } >+ JSObject* baseObject = asObject(baseValue); > >- Identifier ident = Identifier::fromUid(vm, key); >- LOG_IC((ICEvent::OperationIn, base->classInfo(*vm), ident)); >- scope.release(); >- return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident))); >+ LOG_IC((ICEvent::OperationInByIdGeneric, baseObject->classInfo(vm), ident)); >+ >+ PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty); >+ return JSValue::encode(jsBoolean(baseObject->getPropertySlot(exec, ident, slot))); >+} >+ >+EncodedJSValue JIT_OPERATION operationInByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid) >+{ >+ SuperSamplerScope superSamplerScope(false); >+ >+ VM& vm = exec->vm(); >+ NativeCallFrameTracer tracer(&vm, exec); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ Identifier ident = Identifier::fromUid(&vm, uid); >+ >+ JSValue baseValue = JSValue::decode(base); >+ if (!baseValue.isObject()) { >+ throwException(exec, scope, createInvalidInParameterError(exec, baseValue)); >+ return JSValue::encode(jsUndefined()); >+ } >+ JSObject* baseObject = asObject(baseValue); >+ >+ LOG_IC((ICEvent::OperationInByIdOptimize, baseObject->classInfo(vm), ident)); >+ >+ PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty); >+ bool found = baseObject->getPropertySlot(exec, ident, slot); >+ if (stubInfo->considerCaching(exec->codeBlock(), baseObject->structure(vm))) >+ repatchInByID(exec, baseObject, ident, found, slot, *stubInfo); >+ return JSValue::encode(jsBoolean(found)); > } > >-EncodedJSValue JIT_OPERATION operationGenericIn(ExecState* exec, JSCell* base, EncodedJSValue key) >+EncodedJSValue JIT_OPERATION operationInByVal(ExecState* exec, JSCell* base, EncodedJSValue key) > { > SuperSamplerScope superSamplerScope(false); > > VM* vm = &exec->vm(); > NativeCallFrameTracer tracer(vm, exec); > >- return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, base, JSValue::decode(key)))); >+ return JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(exec, base, JSValue::decode(key)))); > } > > void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid) >diff --git a/Source/JavaScriptCore/jit/JITOperations.h b/Source/JavaScriptCore/jit/JITOperations.h >index 7a32669e4e3ded242bf7ce504c8703016569f45c..6071e5dab4d3a256785b54d14b581de1acced266 100644 >--- a/Source/JavaScriptCore/jit/JITOperations.h >+++ b/Source/JavaScriptCore/jit/JITOperations.h >@@ -371,9 +371,12 @@ EncodedJSValue JIT_OPERATION operationGetByIdWithThisOptimize(ExecState*, Struct > EncodedJSValue JIT_OPERATION operationGetByIdDirect(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL; > EncodedJSValue JIT_OPERATION operationGetByIdDirectGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL; > EncodedJSValue JIT_OPERATION operationGetByIdDirectOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL; >+EncodedJSValue JIT_OPERATION operationInById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL; >+EncodedJSValue JIT_OPERATION operationInByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL; >+EncodedJSValue JIT_OPERATION operationInByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL; > EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL; > EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL; >-EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL; >+EncodedJSValue JIT_OPERATION operationInByVal(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL; > void JIT_OPERATION operationPutByIdStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl*) WTF_INTERNAL; > void JIT_OPERATION operationPutByIdNonStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl*) WTF_INTERNAL; > void JIT_OPERATION operationPutByIdDirectStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl*) WTF_INTERNAL; >diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp >index 7e5d107ad22259ea24f3ff5a5a8f1a5b6717eb70..e636f712090ff5098ed6143ea9b8c9a2f8097739 100644 >--- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp >+++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp >@@ -751,6 +751,42 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase > gen.reportSlowPathCall(coldPathBegin, call); > } > >+void JIT::emit_op_in_by_id(Instruction* currentInstruction) >+{ >+ int resultVReg = currentInstruction[1].u.operand; >+ int baseVReg = currentInstruction[2].u.operand; >+ const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); >+ >+ emitGetVirtualRegister(baseVReg, regT0); >+ >+ emitJumpSlowCaseIfNotJSCell(regT0, baseVReg); >+ >+ JITInByIdGenerator gen( >+ m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(), >+ ident->impl(), JSValueRegs(regT0), JSValueRegs(regT0)); >+ gen.generateFastPath(*this); >+ addSlowCase(gen.slowPathJump()); >+ m_inByIds.append(gen); >+ >+ emitPutVirtualRegister(resultVReg); >+} >+ >+void JIT::emitSlow_op_in_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) >+{ >+ linkAllSlowCases(iter); >+ >+ int resultVReg = currentInstruction[1].u.operand; >+ const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); >+ >+ JITInByIdGenerator& gen = m_inByIds[m_inByIdIndex++]; >+ >+ Label coldPathBegin = label(); >+ >+ Call call = callOperation(operationInByIdOptimize, resultVReg, gen.stubInfo(), regT0, ident->impl()); >+ >+ gen.reportSlowPathCall(coldPathBegin, call); >+} >+ > void JIT::emitVarInjectionCheck(bool needsVarInjectionChecks) > { > if (!needsVarInjectionChecks) >diff --git a/Source/JavaScriptCore/jit/Repatch.cpp b/Source/JavaScriptCore/jit/Repatch.cpp >index 14373bbb246718e947def6e92e00250ac4cfdae1..85ec0b204d276f29131c9a88df9f3dc0e1072630 100644 >--- a/Source/JavaScriptCore/jit/Repatch.cpp >+++ b/Source/JavaScriptCore/jit/Repatch.cpp >@@ -605,8 +605,8 @@ void repatchPutByID(ExecState* exec, JSValue baseValue, Structure* structure, co > } > } > >-static InlineCacheAction tryCacheIn( >- ExecState* exec, JSCell* base, const Identifier& ident, >+static InlineCacheAction tryCacheInByID( >+ ExecState* exec, JSObject* base, const Identifier& ident, > bool wasFound, const PropertySlot& slot, StructureStubInfo& stubInfo) > { > VM& vm = exec->vm(); >@@ -631,6 +631,26 @@ static InlineCacheAction tryCacheIn( > std::unique_ptr<PolyProtoAccessChain> prototypeAccessChain; > ObjectPropertyConditionSet conditionSet; > if (wasFound) { >+ InlineCacheAction action = actionForCell(vm, base); >+ if (action != AttemptToCache) >+ return action; >+ >+ // Optimize self access. >+ if (stubInfo.cacheType == CacheType::Unset >+ && slot.isCacheableValue() >+ && slot.slotBase() == base >+ && !slot.watchpointSet() >+ && !structure->needImpurePropertyWatchpoint()) { >+ bool generatedCodeInline = InlineAccess::generateSelfInAccess(stubInfo, structure); >+ if (generatedCodeInline) { >+ LOG_IC((ICEvent::InByIdSelfPatch, structure->classInfo(), ident)); >+ structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset()); >+ ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), operationInByIdOptimize); >+ stubInfo.initInByIdSelf(codeBlock, structure, slot.cachedOffset()); >+ return RetryCacheLater; >+ } >+ } >+ > if (slot.slotBase() != base) { > bool usesPolyProto; > prototypeAccessChain = PolyProtoAccessChain::create(exec->lexicalGlobalObject(), base, slot, usesPolyProto); >@@ -664,7 +684,7 @@ static InlineCacheAction tryCacheIn( > LOG_IC((ICEvent::InAddAccessCase, structure->classInfo(), ident)); > > std::unique_ptr<AccessCase> newCase = AccessCase::create( >- vm, codeBlock, wasFound ? AccessCase::InHit : AccessCase::InMiss, invalidOffset, structure, conditionSet, WTFMove(prototypeAccessChain)); >+ vm, codeBlock, wasFound ? AccessCase::InHit : AccessCase::InMiss, wasFound ? slot.cachedOffset() : invalidOffset, structure, conditionSet, WTFMove(prototypeAccessChain)); > > result = stubInfo.addAccessCase(locker, codeBlock, ident, WTFMove(newCase)); > >@@ -672,10 +692,7 @@ static InlineCacheAction tryCacheIn( > LOG_IC((ICEvent::InReplaceWithJump, structure->classInfo(), ident)); > > RELEASE_ASSERT(result.code()); >- >- MacroAssembler::repatchJump( >- stubInfo.patchableJump(), >- CodeLocationLabel<JITStubRoutinePtrTag>(result.code())); >+ InlineAccess::rewireStubAsJump(stubInfo, CodeLocationLabel<JITStubRoutinePtrTag>(result.code())); > } > } > >@@ -684,13 +701,14 @@ static InlineCacheAction tryCacheIn( > return result.shouldGiveUpNow() ? GiveUpOnCache : RetryCacheLater; > } > >-void repatchIn( >- ExecState* exec, JSCell* base, const Identifier& ident, bool wasFound, >- const PropertySlot& slot, StructureStubInfo& stubInfo) >+void repatchInByID(ExecState* exec, JSObject* baseObject, const Identifier& propertyName, bool wasFound, const PropertySlot& slot, StructureStubInfo& stubInfo) > { > SuperSamplerScope superSamplerScope(false); >- if (tryCacheIn(exec, base, ident, wasFound, slot, stubInfo) == GiveUpOnCache) >- ftlThunkAwareRepatchCall(exec->codeBlock(), stubInfo.slowPathCallLocation(), operationIn); >+ >+ if (tryCacheInByID(exec, baseObject, propertyName, wasFound, slot, stubInfo) == GiveUpOnCache) { >+ CodeBlock* codeBlock = exec->codeBlock(); >+ ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), operationInById); >+ } > } > > static InlineCacheAction tryCacheInstanceOf( >@@ -1236,9 +1254,10 @@ static void resetPatchableJump(StructureStubInfo& stubInfo) > MacroAssembler::repatchJump(stubInfo.patchableJump(), stubInfo.slowPathStartLocation()); > } > >-void resetIn(StructureStubInfo& stubInfo) >+void resetInByID(CodeBlock* codeBlock, StructureStubInfo& stubInfo) > { >- resetPatchableJump(stubInfo); >+ ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), operationInByIdOptimize); >+ InlineAccess::rewireStubAsJump(stubInfo, stubInfo.slowPathStartLocation()); > } > > void resetInstanceOf(StructureStubInfo& stubInfo) >diff --git a/Source/JavaScriptCore/jit/Repatch.h b/Source/JavaScriptCore/jit/Repatch.h >index aa32c26e1b2284ce35bd7eab70fc7332c7b96fd0..0f366ddd8ceb3602cefb1011d600c7ef48d2a15e 100644 >--- a/Source/JavaScriptCore/jit/Repatch.h >+++ b/Source/JavaScriptCore/jit/Repatch.h >@@ -44,7 +44,7 @@ void buildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot > void buildGetByIDProtoList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&); > void repatchPutByID(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind); > void buildPutByIdList(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind); >-void repatchIn(ExecState*, JSCell*, const Identifier&, bool wasFound, const PropertySlot&, StructureStubInfo&); >+void repatchInByID(ExecState*, JSObject*, const Identifier&, bool wasFound, const PropertySlot&, StructureStubInfo&); > void repatchInstanceOf(ExecState*, JSValue value, JSValue prototype, StructureStubInfo&, bool wasFound); > void linkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSObject* callee, MacroAssemblerCodePtr<JSEntryPtrTag>); > void linkDirectFor(ExecState*, CallLinkInfo&, CodeBlock*, MacroAssemblerCodePtr<JSEntryPtrTag>); >@@ -54,7 +54,7 @@ void linkVirtualFor(ExecState*, CallLinkInfo&); > void linkPolymorphicCall(ExecState*, CallLinkInfo&, CallVariant); > void resetGetByID(CodeBlock*, StructureStubInfo&, GetByIDKind); > void resetPutByID(CodeBlock*, StructureStubInfo&); >-void resetIn(StructureStubInfo&); >+void resetInByID(CodeBlock*, StructureStubInfo&); > void resetInstanceOf(StructureStubInfo&); > void ftlThunkAwareRepatchCall(CodeBlock*, CodeLocationCall<JSInternalPtrTag>, FunctionPtr<CFunctionPtrTag> newCalleeFunction); > >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >index 2bc9febfec38578267c060c9f638cb1185581cda..76487059cd764c0a7fce4aa7e106d7ffcef7b259 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >@@ -1507,10 +1507,16 @@ _llint_op_is_function: > dispatch(constexpr op_is_function_length) > > >-_llint_op_in: >+_llint_op_in_by_id: > traceExecution() >- callSlowPath(_slow_path_in) >- dispatch(constexpr op_in_length) >+ callSlowPath(_slow_path_in_by_id) >+ dispatch(constexpr op_in_by_id_length) >+ >+ >+_llint_op_in_by_val: >+ traceExecution() >+ callSlowPath(_slow_path_in_by_val) >+ dispatch(constexpr op_in_by_val_length) > > > _llint_op_try_get_by_id: >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >index 626989d526faeb02a85b20e95d6dcb968abb0ad0..3eea54d6486679d0b4e034d2347e0602ff74bdab 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >@@ -1552,6 +1552,7 @@ _llint_op_put_by_id: > callSlowPath(_llint_slow_path_put_by_id) > dispatch(constexpr op_put_by_id_length) > >+ > macro finishGetByVal(result, scratch) > loadisFromInstruction(1, scratch) > storeq result, [cfr, scratch, 8] >diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h >index e6f03b65b75d00252f043ec9931fbba504b93cde..5d77db19b762ef78414688edc71c89f9f7f6dff9 100644 >--- a/Source/JavaScriptCore/parser/NodeConstructors.h >+++ b/Source/JavaScriptCore/parser/NodeConstructors.h >@@ -623,7 +623,7 @@ namespace JSC { > } > > inline InNode::InNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) >- : ThrowableBinaryOpNode(location, expr1, expr2, op_in, rightHasAssignments) >+ : ThrowableBinaryOpNode(location, expr1, expr2, op_in_by_val, rightHasAssignments) > { > } > >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >index 84dd3d2a4516a188f0f98a01d501004cdc725663..253db5e4aac6114e306f9d4f2094a4b7c3f1a574 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >@@ -648,10 +648,21 @@ SLOW_PATH_DECL(slow_path_is_function) > RETURN(jsBoolean(jsIsFunctionType(OP_C(2).jsValue()))); > } > >-SLOW_PATH_DECL(slow_path_in) >+SLOW_PATH_DECL(slow_path_in_by_val) > { > BEGIN(); >- RETURN(jsBoolean(CommonSlowPaths::opIn(exec, OP_C(2).jsValue(), OP_C(3).jsValue(), pc[4].u.arrayProfile))); >+ RETURN(jsBoolean(CommonSlowPaths::opInByVal(exec, OP_C(2).jsValue(), OP_C(3).jsValue(), pc[4].u.arrayProfile))); >+} >+ >+SLOW_PATH_DECL(slow_path_in_by_id) >+{ >+ BEGIN(); >+ >+ JSValue baseValue = OP_C(2).jsValue(); >+ if (!baseValue.isObject()) >+ THROW(createInvalidInParameterError(exec, baseValue)); >+ >+ RETURN(jsBoolean(asObject(baseValue)->hasProperty(exec, exec->codeBlock()->identifier(pc[3].u.operand)))); > } > > SLOW_PATH_DECL(slow_path_del_by_val) >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h >index db1eea95d48c3e48a95ff86c6cfbca4579b425ba..27c397239f026d656fb12a47703e347295a00ff7 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h >@@ -85,7 +85,7 @@ ALWAYS_INLINE int arityCheckFor(ExecState* exec, VM& vm, CodeSpecializationKind > return padding; > } > >-inline bool opIn(ExecState* exec, JSValue baseVal, JSValue propName, ArrayProfile* arrayProfile = nullptr) >+inline bool opInByVal(ExecState* exec, JSValue baseVal, JSValue propName, ArrayProfile* arrayProfile = nullptr) > { > VM& vm = exec->vm(); > auto scope = DECLARE_THROW_SCOPE(vm); >@@ -306,7 +306,8 @@ SLOW_PATH_HIDDEN_DECL(slow_path_typeof); > SLOW_PATH_HIDDEN_DECL(slow_path_is_object); > SLOW_PATH_HIDDEN_DECL(slow_path_is_object_or_null); > SLOW_PATH_HIDDEN_DECL(slow_path_is_function); >-SLOW_PATH_HIDDEN_DECL(slow_path_in); >+SLOW_PATH_HIDDEN_DECL(slow_path_in_by_id); >+SLOW_PATH_HIDDEN_DECL(slow_path_in_by_val); > SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val); > SLOW_PATH_HIDDEN_DECL(slow_path_strcat); > SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185682
:
340758
|
340773
|
340775
|
340777
|
340779
|
340783