Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Unified Diff: runtime/vm/stub_code_x64.cc

Issue 436643002: Faster IC stubs by specializing them for Binary Smi operations (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/stub_code_x64.cc
===================================================================
--- runtime/vm/stub_code_x64.cc (revision 39456)
+++ runtime/vm/stub_code_x64.cc (working copy)
@@ -1236,6 +1236,81 @@
}
+// Note: RBX must be preserved.
+// Attempt a quick Smi operation for known operations ('kind'). The ICData
+// must have been primed with a Smi/Smi check that will be used for counting
+// the invocations.
+static void EmitFastSmiOp(Assembler* assembler,
+ Token::Kind kind,
+ intptr_t num_args,
+ Label* not_smi_or_overflow) {
+ if (FLAG_throw_on_javascript_int_overflow) {
+ // The overflow check is more complex than implemented below.
+ return;
+ }
+ ASSERT(num_args == 2);
+ __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right
+ __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left.
+ __ movq(R12, RCX);
+ __ orq(R12, RAX);
+ __ testq(R12, Immediate(kSmiTagMask));
+ __ j(NOT_ZERO, not_smi_or_overflow, Assembler::kNearJump);
+ switch (kind) {
+ case Token::kADD: {
+ __ addq(RAX, RCX);
+ __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump);
+ break;
+ }
+ case Token::kSUB: {
+ __ subq(RAX, RCX);
+ __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump);
+ break;
+ }
+ case Token::kEQ: {
+ Label done, is_true;
+ __ cmpq(RAX, RCX);
+ __ j(EQUAL, &is_true, Assembler::kNearJump);
+ __ LoadObject(RAX, Bool::False(), PP);
+ __ jmp(&done, Assembler::kNearJump);
+ __ Bind(&is_true);
+ __ LoadObject(RAX, Bool::True(), PP);
+ __ Bind(&done);
+ break;
+ }
+ default: UNIMPLEMENTED();
+ }
+
+ // RBX: IC data object (preserved).
+ __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
+ // R12: ic_data_array with check entries: classes and target functions.
+ __ leaq(R12, FieldAddress(R12, Array::data_offset()));
+ // R12: points directly to the first ic data array element.
+#if defined(DEBUG)
+ // Check that first entry is for Smi/Smi.
+ Label error, ok;
+ const Immediate& imm_smi_cid =
+ Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid)));
+ __ cmpq(Address(R12, 0 * kWordSize), imm_smi_cid);
+ __ j(NOT_EQUAL, &error, Assembler::kNearJump);
+ __ cmpq(Address(R12, 1 * kWordSize), imm_smi_cid);
+ __ j(EQUAL, &ok, Assembler::kNearJump);
+ __ Bind(&error);
+ __ Stop("Incorrect IC data");
+ __ Bind(&ok);
+#endif
+
+ const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+ // Update counter.
+ __ movq(R8, Address(R12, count_offset));
+ __ addq(R8, Immediate(Smi::RawValue(1)));
+ __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue)));
+ __ cmovnoq(R9, R8);
+ __ movq(Address(R12, count_offset), R9);
+
+ __ ret();
+}
+
+
// Generate inline cache check for 'num_args'.
// RBX: Inline cache data object.
// TOS(0): return address
@@ -1249,7 +1324,8 @@
void StubCode::GenerateNArgsCheckInlineCacheStub(
Assembler* assembler,
intptr_t num_args,
- const RuntimeEntry& handle_ic_miss) {
+ const RuntimeEntry& handle_ic_miss,
+ Token::Kind kind) {
ASSERT(num_args > 0);
#if defined(DEBUG)
{ Label ok;
@@ -1272,6 +1348,12 @@
__ j(NOT_EQUAL, &stepping);
__ Bind(&done_stepping);
+ if (kind != Token::kILLEGAL) {
+ Label not_smi_or_overflow;
+ EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
+ __ Bind(&not_smi_or_overflow);
+ }
+
// Load arguments descriptor into R10.
__ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
// Loop that checks if there is an IC data match.
@@ -1396,24 +1478,46 @@
// - 1 target function.
void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
GenerateUsageCounterIncrement(assembler, RCX);
- GenerateNArgsCheckInlineCacheStub(
- assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry);
+ GenerateNArgsCheckInlineCacheStub(assembler, 1,
+ kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
}
void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
GenerateUsageCounterIncrement(assembler, RCX);
- GenerateNArgsCheckInlineCacheStub(
- assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry);
+ GenerateNArgsCheckInlineCacheStub(assembler, 2,
+ kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
}
void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) {
GenerateUsageCounterIncrement(assembler, RCX);
- GenerateNArgsCheckInlineCacheStub(
- assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry);
+ GenerateNArgsCheckInlineCacheStub(assembler, 3,
+ kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL);
}
+
+void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
+ GenerateUsageCounterIncrement(assembler, RCX);
+ GenerateNArgsCheckInlineCacheStub(assembler, 2,
+ kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
+}
+
+
+void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
+ GenerateUsageCounterIncrement(assembler, RCX);
+ GenerateNArgsCheckInlineCacheStub(assembler, 2,
+ kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
+}
+
+
+void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
+ GenerateUsageCounterIncrement(assembler, RCX);
+ GenerateNArgsCheckInlineCacheStub(assembler, 2,
+ kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
+}
+
+
// Use inline cache data array to invoke the target or continue in inline
// cache miss handler. Stub for 1-argument check (receiver class).
// RDI: function which counter needs to be incremented.
@@ -1428,31 +1532,31 @@
void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
Assembler* assembler) {
GenerateOptimizedUsageCounterIncrement(assembler);
- GenerateNArgsCheckInlineCacheStub(
- assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry);
+ GenerateNArgsCheckInlineCacheStub(assembler, 1,
+ kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
}
void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
Assembler* assembler) {
GenerateOptimizedUsageCounterIncrement(assembler);
- GenerateNArgsCheckInlineCacheStub(
- assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry);
+ GenerateNArgsCheckInlineCacheStub(assembler, 2,
+ kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
}
void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub(
Assembler* assembler) {
GenerateOptimizedUsageCounterIncrement(assembler);
- GenerateNArgsCheckInlineCacheStub(
- assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry);
+ GenerateNArgsCheckInlineCacheStub(assembler, 3,
+ kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL);
}
// Do not count as no type feedback is collected.
void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) {
- GenerateNArgsCheckInlineCacheStub(
- assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry);
+ GenerateNArgsCheckInlineCacheStub(assembler, 1,
+ kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
}
@@ -1521,14 +1625,14 @@
void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
GenerateUsageCounterIncrement(assembler, RCX);
GenerateNArgsCheckInlineCacheStub(
- assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry);
+ assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
}
void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
GenerateUsageCounterIncrement(assembler, RCX);
- GenerateNArgsCheckInlineCacheStub(
- assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry);
+ GenerateNArgsCheckInlineCacheStub(assembler, 2,
+ kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
}

Powered by Google App Engine
This is Rietveld 408576698