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

Unified Diff: runtime/vm/stub_code_ia32.cc

Issue 11272028: Simplify the implementation and generated code for the IC stubs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 2 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
« no previous file with comments | « no previous file | runtime/vm/stub_code_x64.cc » ('j') | runtime/vm/stub_code_x64.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/stub_code_ia32.cc
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index b92645d9e99c216a472589df83acf017b89c89d4..9be505afbc40472fb04de9e95e74f184a613aa53 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1557,8 +1557,18 @@ void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
// - Match not found -> jump to IC miss.
void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
intptr_t num_args) {
- const Immediate raw_null =
- Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ ASSERT(num_args > 0);
+#if defined(DEBUG)
+ { Label ok;
+ // Check that the IC data array has NumberOfArgumentsChecked() == num_args.
+ // 'num_args_tested' is stored as an untagged int.
+ __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset()));
+ __ cmpl(EBX, Immediate(num_args));
+ __ j(EQUAL, &ok, Assembler::kNearJump);
+ __ Stop("Incorrect stub for IC data");
+ __ Bind(&ok);
+ }
+#endif // DEBUG
__ movl(EBX, FieldAddress(ECX, ICData::function_offset()));
Label is_hot;
@@ -1580,70 +1590,63 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
__ incl(FieldAddress(EBX, Function::usage_counter_offset()));
__ Bind(&is_hot);
- ASSERT(num_args > 0);
- // Get receiver (first read number of arguments from argument descriptor array
- // and then access the receiver from the stack).
- __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
- __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi.
-
- Label get_class_id_as_smi, ic_miss;
- // ECX: IC data array.
-
-#if defined(DEBUG)
- { Label ok;
- // Check that the IC data array has NumberOfArgumentsChecked() == num_args.
- // 'num_args_tested' is stored as an untagged int.
- __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset()));
- __ cmpl(EBX, Immediate(num_args));
- __ j(EQUAL, &ok, Assembler::kNearJump);
- __ Stop("Incorrect stub for IC data");
- __ Bind(&ok);
- }
-#endif // DEBUG
-
// Loop that checks if there is an IC data match.
+ Label loop, update, test, found, get_class_id_as_smi;
// ECX: IC data object (preserved).
__ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
// EBX: ic_data_array with check entries: classes and target functions.
__ leal(EBX, FieldAddress(EBX, Array::data_offset()));
// EBX: points directly to the first ic data array element.
- Label loop, found;
- if (num_args == 1) {
- __ call(&get_class_id_as_smi);
- // EAX: receiver's class id Smi.
- __ Bind(&loop);
- __ movl(EDI, Address(EBX, 0)); // Get class id (Smi) to check.
- __ cmpl(EAX, EDI); // Class id match?
- __ j(EQUAL, &found, Assembler::kNearJump);
- __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target).
- __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done?
- __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
- } else {
- Label no_match;
- __ Bind(&loop);
- for (int i = 0; i < num_args; i++) {
+
+ // Get the receiver's class ID (first read number of arguments from
+ // argument descriptor array and then access the receiver from the stack).
+ __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
+ __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is smi.
+ __ call(&get_class_id_as_smi);
+ // EAX: receiver's class ID (smi).
+ __ movl(EDI, Address(EBX, 0)); // First class id (smi) to check.
+ __ jmp(&test);
+
+ __ Bind(&loop);
+ for (int i = 0; i < num_args; i++) {
+ if (i > 0) {
+ // If not the first, load the next argument's class ID.
__ movl(EAX, FieldAddress(EDX, Array::data_offset()));
__ movl(EAX, Address(ESP, EAX, TIMES_2, - i * kWordSize));
__ call(&get_class_id_as_smi);
+ // EAX: next argument class ID (smi).
__ movl(EDI, Address(EBX, i * kWordSize));
- __ cmpl(EAX, EDI); // Class id match?
- if (i < (num_args - 1)) {
- __ j(NOT_EQUAL, &no_match);
- } else {
- // Last check, all checks before matched.
- __ j(EQUAL, &found, Assembler::kNearJump);
- }
+ // EDI: next class ID to check (smi).
+ }
+ __ cmpl(EAX, EDI); // Class id match?
+ if (i < (num_args - 1)) {
+ __ j(NOT_EQUAL, &update); // Continue.
+ } else {
+ // Last check, all checks before matched.
+ __ j(EQUAL, &found, Assembler::kNearJump); // Break.
}
- __ Bind(&no_match);
- // Each test entry has (1 + num_args) array elements.
- __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element.
- __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done?
- __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
}
+ __ Bind(&update);
+ // Reload receiver class ID. It has not been destroyed when num_args == 1.
+ if (num_args > 1) {
+ __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
+ __ movl(EAX, Address(ESP, EAX, TIMES_2, 0));
+ __ call(&get_class_id_as_smi);
+ }
+ // Each test entry has (1 + num_args) array elements.
+ const intptr_t entry_size = (num_args + 1) * kWordSize;
+ __ addl(EBX, Immediate(entry_size)); // Next entry.
+ __ movl(EDI, Address(EBX, 0)); // Next class ID.
+
+ __ Bind(&test);
+ __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done?
+ __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
- __ Bind(&ic_miss);
- // Compute address of arguments (first read number of arguments from argument
- // descriptor array and then compute address on the stack).
+ // IC miss.
+ const Immediate raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ // Compute address of arguments (first read number of arguments from
+ // argument descriptor array and then compute address on the stack).
__ movl(EAX, FieldAddress(EDX, Array::data_offset()));
__ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi.
// Create a stub frame as we are pushing some objects on the stack before
« no previous file with comments | « no previous file | runtime/vm/stub_code_x64.cc » ('j') | runtime/vm/stub_code_x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698