Author: [email protected]
Date: Wed Jun 3 05:04:53 2009
New Revision: 2094
Modified:
branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
branches/bleeding_edge/src/objects.h
branches/bleeding_edge/src/stub-cache.h
branches/bleeding_edge/test/cctest/test-api.cc
Log:
Follow up to r2093: forgotten files and changes.
Modified: branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/stub-cache-ia32.cc (original)
+++ branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Wed Jun 3 05:04:53
2009
@@ -327,6 +327,26 @@
Register scratch1,
Register scratch2,
Label* miss_label) {
+ GenerateLoadInterceptor(masm,
+ object,
+ holder,
+ Smi::FromInt(JSObject::kLookupInHolder),
+ receiver,
+ name,
+ scratch1,
+ scratch2,
+ miss_label);
+}
+
+void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
+ JSObject* object,
+ JSObject* holder,
+ Smi* lookup_hint,
+ Register receiver,
+ Register name,
+ Register scratch1,
+ Register scratch2,
+ Label* miss_label) {
// Check that the receiver isn't a smi.
__ test(receiver, Immediate(kSmiTagMask));
__ j(zero, miss_label, not_taken);
@@ -340,12 +360,15 @@
__ push(receiver); // receiver
__ push(reg); // holder
__ push(name); // name
+ // TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
+ // LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
+ __ push(Immediate(lookup_hint));
__ push(scratch2); // restore return address
// Do tail-call to the runtime system.
ExternalReference load_ic_property =
ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
- __ TailCallRuntime(load_ic_property, 3);
+ __ TailCallRuntime(load_ic_property, 4);
}
@@ -670,11 +693,12 @@
__ push(edx); // receiver
__ push(reg); // holder
__ push(Operand(ebp, (argc + 3) * kPointerSize)); // name
+ __ push(Immediate(holder->InterceptorPropertyLookupHint(name)));
// Perform call.
ExternalReference load_interceptor =
ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
- __ mov(eax, Immediate(3));
+ __ mov(eax, Immediate(4));
__ mov(ebx, Immediate(load_interceptor));
CEntryStub stub;
@@ -974,7 +998,18 @@
Label miss;
__ mov(eax, (Operand(esp, kPointerSize)));
- GenerateLoadInterceptor(masm(), receiver, holder, eax, ecx, edx, ebx,
&miss);
+ // TODO(368): Compile in the whole chain: all the interceptors in
+ // prototypes and ultimate answer.
+ GenerateLoadInterceptor(masm(),
+ receiver,
+ holder,
+ holder->InterceptorPropertyLookupHint(name),
+ eax,
+ ecx,
+ edx,
+ ebx,
+ &miss);
+
__ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC);
Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h (original)
+++ branches/bleeding_edge/src/objects.h Wed Jun 3 05:04:53 2009
@@ -1349,6 +1349,14 @@
Object* LookupCallbackSetterInPrototypes(uint32_t index);
void LookupCallback(String* name, LookupResult* result);
+ inline Smi* InterceptorPropertyLookupHint(String* name);
+ Object* GetInterceptorPropertyWithLookupHint(JSObject* receiver,
+ Smi* lookup_hint,
+ String* name,
+ PropertyAttributes*
attributes);
+ static const int kLookupInHolder = -1;
+ static const int kLookupInPrototype = -2;
+
// Returns the number of properties on this object filtering out
properties
// with the specified attributes (ignoring interceptors).
int NumberOfLocalProperties(PropertyAttributes filter);
@@ -1539,6 +1547,10 @@
Object* DefineGetterSetter(String* name, PropertyAttributes attributes);
void LookupInDescriptor(String* name, LookupResult* result);
+
+ Object* GetPropertyWithInterceptorProper(JSObject* receiver,
+ String* name,
+ PropertyAttributes* attributes);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
};
Modified: branches/bleeding_edge/src/stub-cache.h
==============================================================================
--- branches/bleeding_edge/src/stub-cache.h (original)
+++ branches/bleeding_edge/src/stub-cache.h Wed Jun 3 05:04:53 2009
@@ -356,6 +356,16 @@
Register scratch1,
Register scratch2,
Label* miss_label);
+ // TODO(antonm): Remove a function above.
+ static void GenerateLoadInterceptor(MacroAssembler* masm,
+ JSObject* object,
+ JSObject* holder,
+ Smi* lookup_hint,
+ Register receiver,
+ Register name,
+ Register scratch1,
+ Register scratch2,
+ Label* miss_label);
static void GenerateLoadArrayLength(MacroAssembler* masm,
Register receiver,
Register scratch,
Modified: branches/bleeding_edge/test/cctest/test-api.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-api.cc (original)
+++ branches/bleeding_edge/test/cctest/test-api.cc Wed Jun 3 05:04:53 2009
@@ -4844,6 +4844,90 @@
}
+// Below go several tests which verify that JITing for various
+// configurations of interceptor and explicit fields works fine
+// (those cases are special cased to get better performance).
+
+static v8::Handle<Value> InterceptorLoadXICGetter(Local<String> name,
+ const AccessorInfo& info)
{
+ ApiTestFuzzer::Fuzz();
+ return v8_str("x")->Equals(name)
+ ? v8::Integer::New(42) : v8::Handle<v8::Value>();
+}
+
+
+static void CheckInterceptorLoadIC(const char* source, int expected) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+ LocalContext context;
+ context->Global()->Set(v8_str("o"), templ->NewInstance());
+ v8::Handle<Value> value = CompileRun(source);
+ CHECK_EQ(expected, value->Int32Value());
+}
+
+
+THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
+ CheckInterceptorLoadIC(
+ "var result = 0;"
+ "o.y = 239;"
+ "for (var i = 0; i < 1000; i++) {"
+ " result = o.y;"
+ "}",
+ 239);
+}
+
+
+THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
+ CheckInterceptorLoadIC(
+ "var result = 0;"
+ "o.__proto__ = { 'y': 239 };"
+ "for (var i = 0; i < 1000; i++) {"
+ " result = o.y + o.x;"
+ "}",
+ 239 + 42);
+}
+
+
+THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
+ CheckInterceptorLoadIC(
+ "var result = 0;"
+ "o.__proto__.y = 239;"
+ "for (var i = 0; i < 1000; i++) {"
+ " result = o.y + o.x;"
+ "}",
+ 239 + 42);
+}
+
+
+THREADED_TEST(InterceptorLoadICUndefined) {
+ CheckInterceptorLoadIC(
+ "var result = 0;"
+ "for (var i = 0; i < 1000; i++) {"
+ " result = (o.y == undefined) ? 239 : 42;"
+ "}",
+ 239);
+}
+
+
+THREADED_TEST(InterceptorLoadICWithOverride) {
+ CheckInterceptorLoadIC(
+ "fst = new Object(); fst.__proto__ = o;"
+ "snd = new Object(); snd.__proto__ = fst;"
+ "var result1 = 0;"
+ "for (var i = 0; i < 1000; i++) {"
+ " result1 = snd.x;"
+ "}"
+ "fst.x = 239;"
+ "var result = 0;"
+ "for (var i = 0; i < 1000; i++) {"
+ " result = snd.x;"
+ "}"
+ "result + result1",
+ 239 + 42);
+}
+
+
static v8::Handle<Value> InterceptorStoreICSetter(
Local<String> key, Local<Value> value, const AccessorInfo&) {
CHECK(v8_str("x")->Equals(key));
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---