Revision: 4401
Author: [email protected]
Date: Tue Apr 13 23:25:11 2010
Log: Add inline caches for loading non-existing properties.
Review URL: http://codereview.chromium.org/1539034
http://code.google.com/p/v8/source/detail?r=4401
Modified:
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/globals.h
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/stub-cache.cc
/branches/bleeding_edge/src/stub-cache.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Mar 25 10:08:22
2010
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Tue Apr 13 23:25:11
2010
@@ -1387,6 +1387,36 @@
// Return the generated code.
return GetCode(NORMAL, name);
}
+
+
+Object* LoadStubCompiler::CompileLoadNonexistent(JSObject* object) {
+ // ----------- S t a t e -------------
+ // -- r2 : name
+ // -- lr : return address
+ // -- [sp] : receiver
+ // -----------------------------------
+ Label miss;
+
+ // Load receiver.
+ __ ldr(r0, MemOperand(sp, 0));
+
+ // Check the maps of the full prototype chain.
+ JSObject* last = object;
+ while (last->GetPrototype() != Heap::null_value()) {
+ last = JSObject::cast(last->GetPrototype());
+ }
+ CheckPrototypes(object, r0, last, r3, r1, Heap::empty_string(), &miss);
+
+ // Return undefined if maps of the full prototype chain is still the
same.
+ __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
+ __ Ret();
+
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+ // Return the generated code.
+ return GetCode(NONEXISTENT, Heap::empty_string());
+}
Object* LoadStubCompiler::CompileLoadField(JSObject* object,
=======================================
--- /branches/bleeding_edge/src/globals.h Mon Apr 12 00:23:43 2010
+++ /branches/bleeding_edge/src/globals.h Tue Apr 13 23:25:11 2010
@@ -428,7 +428,11 @@
CONSTANT_TRANSITION = 6, // only in fast mode
NULL_DESCRIPTOR = 7, // only in fast mode
// All properties before MAP_TRANSITION are real.
- FIRST_PHANTOM_PROPERTY_TYPE = MAP_TRANSITION
+ FIRST_PHANTOM_PROPERTY_TYPE = MAP_TRANSITION,
+ // There are no IC stubs for NULL_DESCRIPTORS. Therefore,
+ // NULL_DESCRIPTOR can be used as the type flag for IC stubs for
+ // nonexistent properties.
+ NONEXISTENT = NULL_DESCRIPTOR
};
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Mar 25 10:08:22
2010
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Apr 13 23:25:11
2010
@@ -1948,6 +1948,32 @@
}
+Object* LoadStubCompiler::CompileLoadNonexistent(JSObject* object) {
+ // ----------- S t a t e -------------
+ // -- eax : receiver
+ // -- ecx : name
+ // -- esp[0] : return address
+ // -----------------------------------
+ Label miss;
+
+ // Check the maps of the full prototype chain.
+ JSObject* last = object;
+ while (last->GetPrototype() != Heap::null_value()) {
+ last = JSObject::cast(last->GetPrototype());
+ }
+ CheckPrototypes(object, eax, last, ebx, edx, Heap::empty_string(),
&miss);
+
+ // Return undefined if maps of the full prototype chain is still the
same.
+ __ mov(eax, Factory::undefined_value());
+ __ ret(0);
+
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+ // Return the generated code.
+ return GetCode(NONEXISTENT, Heap::empty_string());
+}
+
Object* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder,
=======================================
--- /branches/bleeding_edge/src/ic.cc Thu Apr 8 08:19:06 2010
+++ /branches/bleeding_edge/src/ic.cc Tue Apr 13 23:25:11 2010
@@ -694,8 +694,8 @@
State state,
Handle<Object> object,
Handle<String> name) {
- // Bail out if we didn't find a result.
- if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
+ // Bail out if the result is not cachable.
+ if (!lookup->IsCacheable()) return;
// Loading properties from values is not common, so don't try to
// deal with non-JS objects here.
@@ -709,6 +709,9 @@
// Set the target to the pre monomorphic stub to delay
// setting the monomorphic state.
code = pre_monomorphic_stub();
+ } else if (!lookup->IsProperty()) {
+ // Nonexistent property. The result is undefined.
+ code = StubCache::ComputeLoadNonexistent(*name, *receiver);
} else {
// Compute monomorphic stub.
switch (lookup->type()) {
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/src/stub-cache.cc Tue Apr 13 23:25:11 2010
@@ -91,6 +91,28 @@
primary->value = code;
return code;
}
+
+
+Object* StubCache::ComputeLoadNonexistent(String* name, JSObject*
receiver) {
+ // The code stub for loading nonexistent properties can be reused
+ // for all names, so we use the empty_string as the name in the map
+ // code cache.
+ Code::Flags flags =
+ Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
+ Object* code = receiver->map()->FindInCodeCache(Heap::empty_string(),
flags);
+ if (code->IsUndefined()) {
+ LoadStubCompiler compiler;
+ code = compiler.CompileLoadNonexistent(receiver);
+ if (code->IsFailure()) return code;
+ PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG,
+ Code::cast(code),
+ Heap::empty_string()));
+ Object* result = receiver->map()->UpdateCodeCache(Heap::empty_string(),
+ Code::cast(code));
+ if (result->IsFailure()) return result;
+ }
+ return Set(name, receiver->map(), Code::cast(code));
+}
Object* StubCache::ComputeLoadField(String* name,
=======================================
--- /branches/bleeding_edge/src/stub-cache.h Tue Mar 23 07:33:42 2010
+++ /branches/bleeding_edge/src/stub-cache.h Tue Apr 13 23:25:11 2010
@@ -56,6 +56,8 @@
// Computes the right stub matching. Inserts the result in the
// cache before returning. This might compile a stub if needed.
+ static Object* ComputeLoadNonexistent(String* name, JSObject* receiver);
+
static Object* ComputeLoadField(String* name,
JSObject* receiver,
JSObject* holder,
@@ -461,18 +463,23 @@
class LoadStubCompiler: public StubCompiler {
public:
+ Object* CompileLoadNonexistent(JSObject* object);
+
Object* CompileLoadField(JSObject* object,
JSObject* holder,
int index,
String* name);
+
Object* CompileLoadCallback(String* name,
JSObject* object,
JSObject* holder,
AccessorInfo* callback);
+
Object* CompileLoadConstant(JSObject* object,
JSObject* holder,
Object* value,
String* name);
+
Object* CompileLoadInterceptor(JSObject* object,
JSObject* holder,
String* name);
@@ -494,17 +501,21 @@
JSObject* object,
JSObject* holder,
int index);
+
Object* CompileLoadCallback(String* name,
JSObject* object,
JSObject* holder,
AccessorInfo* callback);
+
Object* CompileLoadConstant(String* name,
JSObject* object,
JSObject* holder,
Object* value);
+
Object* CompileLoadInterceptor(JSObject* object,
JSObject* holder,
String* name);
+
Object* CompileLoadArrayLength(String* name);
Object* CompileLoadStringLength(String* name);
Object* CompileLoadFunctionPrototype(String* name);
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Thu Mar 25 10:08:22
2010
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue Apr 13 23:25:11
2010
@@ -1142,6 +1142,36 @@
// Return the generated code.
return GetCode(CONSTANT_FUNCTION, name);
}
+
+
+Object* LoadStubCompiler::CompileLoadNonexistent(JSObject* object) {
+ // ----------- S t a t e -------------
+ // -- rcx : name
+ // -- rsp[0] : return address
+ // -- rsp[8] : receiver
+ // -----------------------------------
+ Label miss;
+
+ // Load receiver.
+ __ movq(rax, Operand(rsp, kPointerSize));
+
+ // Check the maps of the full prototype chain.
+ JSObject* last = object;
+ while (last->GetPrototype() != Heap::null_value()) {
+ last = JSObject::cast(last->GetPrototype());
+ }
+ CheckPrototypes(object, rax, last, rbx, rdx, Heap::empty_string(),
&miss);
+
+ // Return undefined if maps of the full prototype chain is still the
same.
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
+ __ ret(0);
+
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+ // Return the generated code.
+ return GetCode(NONEXISTENT, Heap::empty_string());
+}
Object* LoadStubCompiler::CompileLoadField(JSObject* object,
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
To unsubscribe, reply using "remove me" as the subject.