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

Unified Diff: src/ia32/stub-cache-ia32.cc

Issue 12209021: Refactor LoadIC into Handler Frontend and Backends. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 10 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 | src/ic.h » ('j') | src/stub-cache.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/stub-cache-ia32.cc
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 96dc46bc72fdd96570d7ec55ce1b647016da9f9d..c753d4e353882a1939d067cc06a74d924acbaa5a 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -1044,46 +1044,20 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
}
-void StubCompiler::GenerateLoadField(Handle<JSObject> object,
- Handle<JSObject> holder,
- Register receiver,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- PropertyIndex index,
- Handle<String> name,
- Label* miss) {
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
-
- // Check the prototype chain.
- Register reg = CheckPrototypes(
- object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
-
- // Get the value from the properties.
- GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
- __ ret(0);
-}
-
-
-void StubCompiler::GenerateDictionaryLoadCallback(Register receiver,
- Register name_reg,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Handle<AccessorInfo> callback,
- Handle<String> name,
- Label* miss) {
- ASSERT(!receiver.is(scratch2));
- ASSERT(!receiver.is(scratch3));
- Register dictionary = scratch1;
- bool must_preserve_dictionary_reg = receiver.is(dictionary);
+void BaseLoadStubCompiler::GenerateDictionaryLoadCallback(
Toon Verwaest 2013/02/06 14:06:30 This got moved into CallbackHandlerFrontend direct
+ Register reg,
+ Handle<AccessorInfo> callback,
+ Label* miss) {
+ ASSERT(!reg.is(scratch2()));
+ ASSERT(!reg.is(scratch3()));
+ Register dictionary = scratch1();
+ bool must_preserve_dictionary_reg = reg.is(dictionary);
// Load the properties dictionary.
if (must_preserve_dictionary_reg) {
__ push(dictionary);
}
- __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset));
+ __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset));
// Probe the dictionary.
Label probe_done, pop_and_miss;
@@ -1091,9 +1065,9 @@ void StubCompiler::GenerateDictionaryLoadCallback(Register receiver,
&pop_and_miss,
&probe_done,
dictionary,
- name_reg,
- scratch2,
- scratch3);
+ this->name(),
+ scratch2(),
+ scratch3());
__ bind(&pop_and_miss);
if (must_preserve_dictionary_reg) {
__ pop(dictionary);
@@ -1103,56 +1077,79 @@ void StubCompiler::GenerateDictionaryLoadCallback(Register receiver,
// If probing finds an entry in the dictionary, scratch2 contains the
// index into the dictionary. Check that the value is the callback.
- Register index = scratch2;
+ Register index = scratch2();
const int kElementsStartOffset =
StringDictionary::kHeaderSize +
StringDictionary::kElementsStartIndex * kPointerSize;
const int kValueOffset = kElementsStartOffset + kPointerSize;
- __ mov(scratch3,
+ __ mov(scratch3(),
Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag));
if (must_preserve_dictionary_reg) {
__ pop(dictionary);
}
- __ cmp(scratch3, callback);
+ __ cmp(scratch3(), callback);
__ j(not_equal, miss);
}
-void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
- Handle<JSObject> holder,
- Register receiver,
- Register name_reg,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Register scratch4,
- Handle<AccessorInfo> callback,
- Handle<String> name,
- Label* miss) {
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
+Register BaseLoadStubCompiler::GenerateHandlerFrontend(
+ Handle<JSObject> object,
+ Register object_reg,
+ Handle<JSObject> holder,
+ Handle<String> name,
+ Label* success,
+ Handle<AccessorInfo> callback,
+ bool perform_initial_checks) {
+ Label miss;
- // Check that the maps haven't changed.
- Register reg = CheckPrototypes(object, receiver, holder, scratch1,
- scratch2, scratch3, name, miss);
+ if (perform_initial_checks) {
+ GenerateNameCheck(name, this->name(), &miss);
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(object_reg, &miss);
+ }
- if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
- GenerateDictionaryLoadCallback(
- reg, name_reg, scratch1, scratch2, scratch3, callback, name, miss);
+ // Check the prototype chain.
+ Register reg = CheckPrototypes(object, object_reg, holder,
+ scratch1(), scratch2(), scratch3(),
+ name, &miss);
+
+ if (!callback.is_null() &&
+ !holder->HasFastProperties() &&
+ !holder->IsJSGlobalObject()) {
+ GenerateDictionaryLoadCallback(reg, callback, &miss);
}
+ __ jmp(success);
+
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), kind());
+ return reg;
+}
+
+
+void BaseLoadStubCompiler::GenerateLoadField(Register reg,
+ Handle<JSObject> holder,
+ PropertyIndex index) {
+ // Get the value from the properties.
+ GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
+ __ ret(0);
+}
+
+
+void BaseLoadStubCompiler::GenerateLoadCallback(Register reg,
+ Handle<AccessorInfo> callback) {
// Insert additional parameters into the stack frame above return address.
- ASSERT(!scratch3.is(reg));
- __ pop(scratch3); // Get return address to place it below.
+ ASSERT(!scratch3().is(reg));
+ __ pop(scratch3()); // Get return address to place it below.
- __ push(receiver); // receiver
- __ mov(scratch2, esp);
- ASSERT(!scratch2.is(reg));
+ __ push(receiver()); // receiver
+ __ mov(scratch2(), esp);
+ ASSERT(!scratch2().is(reg));
__ push(reg); // holder
// Push data from AccessorInfo.
if (isolate()->heap()->InNewSpace(callback->data())) {
- __ mov(scratch1, Immediate(callback));
- __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));
+ __ mov(scratch1(), Immediate(callback));
+ __ push(FieldOperand(scratch1(), AccessorInfo::kDataOffset));
} else {
__ push(Immediate(Handle<Object>(callback->data())));
}
@@ -1160,12 +1157,12 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
// Save a pointer to where we pushed the arguments pointer.
// This will be passed as the const AccessorInfo& to the C++ callback.
- __ push(scratch2);
+ __ push(scratch2());
- __ push(name_reg); // name
+ __ push(name()); // name
__ mov(ebx, esp); // esp points to reference to name (handler).
- __ push(scratch3); // Restore return address.
+ __ push(scratch3()); // Restore return address.
// 4 elements array for v8::Arguments::values_, handler for name and pointer
// to the values (it considered as smi in GC).
@@ -1186,44 +1183,22 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
}
-void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
- Handle<JSObject> holder,
- Register receiver,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Handle<JSFunction> value,
- Handle<String> name,
- Label* miss) {
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
-
- // Check that the maps haven't changed.
- CheckPrototypes(
- object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
-
+void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) {
// Return the constant value.
__ LoadHeapObject(eax, value);
__ ret(0);
}
-void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
- Handle<JSObject> interceptor_holder,
- LookupResult* lookup,
- Register receiver,
- Register name_reg,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Handle<String> name,
- Label* miss) {
+void BaseLoadStubCompiler::GenerateLoadInterceptor(
+ Register holder_reg,
+ Handle<JSObject> object,
+ Handle<JSObject> interceptor_holder,
+ LookupResult* lookup,
+ Handle<String> name) {
ASSERT(interceptor_holder->HasNamedInterceptor());
ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
-
// So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added
// later.
@@ -1243,17 +1218,14 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
// Compile the interceptor call, followed by inline code to load the
// property from further up the prototype chain if the call fails.
// Check that the maps haven't changed.
- Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
- scratch1, scratch2, scratch3,
- name, miss);
- ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
+ ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
// Preserve the receiver register explicitly whenever it is different from
// the holder and it is needed should the interceptor return without any
// result. The CALLBACKS case needs the receiver to be passed into C++ code,
// the FIELD case might cause a miss during the prototype check.
bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
Jakob Kummerow 2013/02/06 12:48:27 While you're at it: s/perfrom/perform/
- bool must_preserve_receiver_reg = !receiver.is(holder_reg) &&
+ bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
(lookup->type() == CALLBACKS || must_perfrom_prototype_check);
// Save necessary data before invoking an interceptor.
@@ -1262,18 +1234,18 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
FrameScope frame_scope(masm(), StackFrame::INTERNAL);
if (must_preserve_receiver_reg) {
- __ push(receiver);
+ __ push(receiver());
}
__ push(holder_reg);
- __ push(name_reg);
+ __ push(this->name());
// Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
// of this method.)
CompileCallLoadPropertyWithInterceptor(masm(),
- receiver,
+ receiver(),
holder_reg,
- name_reg,
+ this->name(),
interceptor_holder);
// Check if interceptor provided a value for property. If it's
@@ -1287,76 +1259,28 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
// Clobber registers when generating debug-code to provoke errors.
__ bind(&interceptor_failed);
if (FLAG_debug_code) {
- __ mov(receiver, Immediate(BitCast<int32_t>(kZapValue)));
+ __ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue)));
__ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue)));
- __ mov(name_reg, Immediate(BitCast<int32_t>(kZapValue)));
+ __ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue)));
}
- __ pop(name_reg);
+ __ pop(this->name());
__ pop(holder_reg);
if (must_preserve_receiver_reg) {
- __ pop(receiver);
+ __ pop(receiver());
}
// Leave the internal frame.
}
- // Check that the maps from interceptor's holder to lookup's holder
- // haven't changed. And load lookup's holder into holder_reg.
- if (must_perfrom_prototype_check) {
- holder_reg = CheckPrototypes(interceptor_holder,
- holder_reg,
- Handle<JSObject>(lookup->holder()),
- scratch1,
- scratch2,
- scratch3,
- name,
- miss);
- }
-
- if (lookup->IsField()) {
- // We found FIELD property in prototype chain of interceptor's holder.
- // Retrieve a field from field's holder.
- GenerateFastPropertyLoad(masm(), eax, holder_reg,
- Handle<JSObject>(lookup->holder()),
- lookup->GetFieldIndex());
- __ ret(0);
- } else {
- // We found CALLBACKS property in prototype chain of interceptor's
- // holder.
- ASSERT(lookup->type() == CALLBACKS);
- Handle<AccessorInfo> callback(
- AccessorInfo::cast(lookup->GetCallbackObject()));
- ASSERT(callback->getter() != NULL);
-
- // Tail call to runtime.
- // Important invariant in CALLBACKS case: the code above must be
- // structured to never clobber |receiver| register.
- __ pop(scratch2); // return address
- __ push(receiver);
- __ push(holder_reg);
- __ mov(holder_reg, Immediate(callback));
- __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
- __ push(Immediate(reinterpret_cast<int>(isolate())));
- __ push(holder_reg);
- __ push(name_reg);
- __ push(scratch2); // restore return address
-
- ExternalReference ref =
- ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
- masm()->isolate());
- __ TailCallExternalReference(ref, 6, 1);
- }
+ GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
} else { // !compile_followup_inline
// Call the runtime system to load the interceptor.
// Check that the maps haven't changed.
- Register holder_reg =
- CheckPrototypes(object, receiver, interceptor_holder,
- scratch1, scratch2, scratch3, name, miss);
- __ pop(scratch2); // save old return address
- PushInterceptorArguments(masm(), receiver, holder_reg,
- name_reg, interceptor_holder);
- __ push(scratch2); // restore old return address
+ __ pop(scratch2()); // save old return address
+ PushInterceptorArguments(masm(), receiver(), holder_reg,
+ this->name(), interceptor_holder);
+ __ push(scratch2()); // restore old return address
ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
@@ -1366,6 +1290,46 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
}
+void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
+ Register interceptor_reg,
+ Handle<JSObject> interceptor_holder,
+ Handle<String> name,
+ LookupResult* lookup) {
+ Label success;
+ Handle<JSObject> holder(lookup->holder());
+ if (lookup->IsField()) {
+ // We found FIELD property in prototype chain of interceptor's holder.
+ // Retrieve a field from field's holder.
+ Register reg = GenerateHandlerFrontend(interceptor_holder,
+ interceptor_reg,
+ holder,
+ name,
+ &success,
+ Handle<AccessorInfo>::null(),
+ false);
+ __ bind(&success);
+ GenerateLoadField(reg, holder, lookup->GetFieldIndex());
+ } else {
+ // We found CALLBACKS property in prototype chain of interceptor's
+ // holder.
+ ASSERT(lookup->type() == CALLBACKS);
+ Handle<AccessorInfo> callback(
+ AccessorInfo::cast(lookup->GetCallbackObject()));
+ ASSERT(callback->getter() != NULL);
+
+ Register reg = GenerateHandlerFrontend(interceptor_holder,
+ interceptor_reg,
+ holder,
+ name,
+ &success,
+ callback,
+ false);
+ __ bind(&success);
+ GenerateLoadCallback(reg, callback);
+ }
+}
+
+
void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
__ cmp(ecx, Immediate(name));
« no previous file with comments | « no previous file | src/ic.h » ('j') | src/stub-cache.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698