Index: runtime/vm/stub_code_x64.cc |
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc |
index 39d8dc96b0b2c7e2d040fa48f1b89270e7cceed6..e562e559ff6040d25961f11e23613c3631f46d2b 100644 |
--- a/runtime/vm/stub_code_x64.cc |
+++ b/runtime/vm/stub_code_x64.cc |
@@ -2088,6 +2088,13 @@ void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
} |
+// Called from megamorphic calls. |
+// RDI: receiver |
+// RBX: MegamorphicCache (preserved) |
+// Result: |
+// RCX: target entry point |
+// CODE_REG: target Code |
+// R10: arguments descriptor |
void StubCode::EmitMegamorphicLookup(Assembler* assembler) { |
__ LoadTaggedClassIdMayBeSmi(RAX, RDI); |
// RAX: class ID of the receiver (smi). |
@@ -2127,13 +2134,6 @@ void StubCode::EmitMegamorphicLookup(Assembler* assembler) { |
} |
-// Called from megamorphic calls. |
-// RDI: receiver |
-// RBX: MegamorphicCache (preserved) |
-// Result: |
-// RCX: target entry point |
-// CODE_REG: target Code |
-// R10: arguments descriptor |
void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
EmitMegamorphicLookup(assembler); |
__ ret(); |
@@ -2147,7 +2147,53 @@ void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
// RCX: target entry point |
// CODE_REG: target Code object |
// R10: arguments descriptor |
-void StubCode::GenerateICLookupStub(Assembler* assembler) { |
+static void EmitICLookup(Assembler* assembler, |
+ intptr_t args_checked, |
+ Token::Kind kind) { |
+ if (kind != Token::kILLEGAL) { |
+ __ Comment("Fast Smi op"); |
+ Label not_smi_or_overflow; |
+ |
+ // RDI: Receiver |
+ __ movq(RCX, Address(RSP, + 1 * kWordSize)); |
+ // RCX: Argument |
+ __ movq(R13, RCX); |
+ __ orq(R13, RDI); |
+ __ testq(R13, Immediate(kSmiTagMask)); |
+ __ j(NOT_ZERO, ¬_smi_or_overflow); |
+ __ movq(RAX, RDI); |
+ switch (kind) { |
+ case Token::kADD: { |
+ __ addq(RAX, RCX); |
+ __ j(OVERFLOW, ¬_smi_or_overflow); |
+ break; |
+ } |
+ case Token::kSUB: { |
+ __ subq(RAX, RCX); |
+ __ j(OVERFLOW, ¬_smi_or_overflow); |
+ break; |
+ } |
+ case Token::kEQ: { |
+ Label done, is_true; |
+ __ cmpq(RAX, RCX); |
+ __ j(EQUAL, &is_true, Assembler::kNearJump); |
+ __ LoadObject(RAX, Bool::False()); |
+ __ jmp(&done, Assembler::kNearJump); |
+ __ Bind(&is_true); |
+ __ LoadObject(RAX, Bool::True()); |
+ __ Bind(&done); |
+ break; |
+ } |
+ default: UNIMPLEMENTED(); |
+ } |
+ // Return past the call to lookup result. |
+ intptr_t call_length = 2; // call rcx |
+ __ AddImmediate(Address(RSP, 0), Immediate(call_length)); |
+ __ ret(); |
+ |
+ __ Bind(¬_smi_or_overflow); |
+ } |
+ |
Label loop, found, miss; |
__ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); |
@@ -2166,12 +2212,14 @@ void StubCode::GenerateICLookupStub(Assembler* assembler) { |
__ testq(R9, R9); |
__ j(ZERO, &miss, Assembler::kNearJump); |
- const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; |
+ const intptr_t entry_length = |
+ ICData::TestEntryLengthFor(args_checked) * kWordSize; |
__ addq(R13, Immediate(entry_length)); // Next entry. |
__ jmp(&loop); |
__ Bind(&found); |
- const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; |
+ const intptr_t target_offset = |
+ ICData::TargetIndexFor(args_checked) * kWordSize; |
__ movq(RAX, Address(R13, target_offset)); |
__ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
__ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
@@ -2184,6 +2232,26 @@ void StubCode::GenerateICLookupStub(Assembler* assembler) { |
__ ret(); |
} |
+ |
+void StubCode::GenerateICLookupStub(Assembler* assembler) { |
+ EmitICLookup(assembler, 1, Token::kILLEGAL); |
+} |
+ |
+ |
+void StubCode::GenerateICSmiAddLookupStub(Assembler* assembler) { |
+ EmitICLookup(assembler, 2, Token::kADD); |
+} |
+ |
+ |
+void StubCode::GenerateICSmiSubLookupStub(Assembler* assembler) { |
+ EmitICLookup(assembler, 2, Token::kSUB); |
+} |
+ |
+ |
+void StubCode::GenerateICSmiEqualLookupStub(Assembler* assembler) { |
+ EmitICLookup(assembler, 2, Token::kEQ); |
+} |
+ |
} // namespace dart |
#endif // defined TARGET_ARCH_X64 |