Commit dfbc850e authored by kasperl@chromium.org's avatar kasperl@chromium.org

Revert revision 2108. This brings back the changes

submitted in revisions 2093, 2094, 2099, and 2106.
There's no evidence that supports that these changes
should be the cause of the unexplained performance
regressions on the intl2 and DHTML page cyclers. 


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2109 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 84c09c6d
......@@ -246,6 +246,7 @@ void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
JSObject* object,
JSObject* holder,
Smi* lookup_hint,
Register receiver,
Register name,
Register scratch1,
......@@ -263,11 +264,13 @@ void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
__ push(receiver); // receiver
__ push(reg); // holder
__ push(name); // name
__ mov(scratch1, Operand(lookup_hint));
__ push(scratch1);
// 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);
}
......@@ -909,7 +912,15 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
__ ldr(r0, MemOperand(sp, 0));
GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
GenerateLoadInterceptor(masm(),
object,
holder,
holder->InterceptorPropertyLookupHint(name),
r0,
r2,
r3,
r1,
&miss);
__ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC);
......@@ -1015,7 +1026,15 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ cmp(r2, Operand(Handle<String>(name)));
__ b(ne, &miss);
GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
GenerateLoadInterceptor(masm(),
receiver,
holder,
Smi::FromInt(JSObject::kLookupInHolder),
r0,
r2,
r3,
r1,
&miss);
__ bind(&miss);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
......
......@@ -322,6 +322,7 @@ void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
JSObject* object,
JSObject* holder,
Smi* lookup_hint,
Register receiver,
Register name,
Register scratch1,
......@@ -340,12 +341,15 @@ void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
__ 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 +674,12 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
__ 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 +979,18 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
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);
......@@ -1089,7 +1105,15 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss, not_taken);
GenerateLoadInterceptor(masm(), receiver, holder, ecx, eax, edx, ebx, &miss);
GenerateLoadInterceptor(masm(),
receiver,
holder,
Smi::FromInt(JSObject::kLookupInHolder),
ecx,
eax,
edx,
ebx,
&miss);
__ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_interceptor, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
......
......@@ -2554,6 +2554,24 @@ bool JSObject::HasElement(uint32_t index) {
}
Smi* JSObject::InterceptorPropertyLookupHint(String* name) {
// TODO(antonm): Do we want to do any shortcuts for global object?
if (HasFastProperties()) {
LookupResult lookup;
LocalLookupRealNamedProperty(name, &lookup);
if (lookup.IsValid()) {
if (lookup.type() == FIELD && lookup.IsCacheable()) {
return Smi::FromInt(lookup.GetFieldIndex());
}
} else {
return Smi::FromInt(kLookupInPrototype);
}
}
return Smi::FromInt(kLookupInHolder);
}
bool AccessorInfo::all_can_read() {
return BooleanBit::get(flag(), kAllCanReadBit);
}
......
......@@ -5617,9 +5617,11 @@ Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver,
}
Object* JSObject::GetPropertyWithInterceptor(JSObject* receiver,
String* name,
PropertyAttributes* attributes) {
bool JSObject::GetPropertyWithInterceptorProper(
JSObject* receiver,
String* name,
PropertyAttributes* attributes,
Object** result_object) {
HandleScope scope;
Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
Handle<JSObject> receiver_handle(receiver);
......@@ -5640,19 +5642,93 @@ Object* JSObject::GetPropertyWithInterceptor(JSObject* receiver,
VMState state(EXTERNAL);
result = getter(v8::Utils::ToLocal(name_handle), info);
}
RETURN_IF_SCHEDULED_EXCEPTION();
if (Top::has_scheduled_exception()) {
return false;
}
if (!result.IsEmpty()) {
*attributes = NONE;
return *v8::Utils::OpenHandle(*result);
*result_object = *v8::Utils::OpenHandle(*result);
return true;
}
}
Object* raw_result = holder_handle->GetPropertyPostInterceptor(
return false;
}
Object* JSObject::GetInterceptorPropertyWithLookupHint(
JSObject* receiver,
Smi* lookup_hint,
String* name,
PropertyAttributes* attributes) {
HandleScope scope;
Handle<JSObject> receiver_handle(receiver);
Handle<JSObject> holder_handle(this);
Handle<String> name_handle(name);
Object* result = NULL;
if (GetPropertyWithInterceptorProper(receiver, name, attributes, &result)) {
return result;
} else {
RETURN_IF_SCHEDULED_EXCEPTION();
}
int property_index = lookup_hint->value();
if (property_index >= 0) {
result = holder_handle->FastPropertyAt(property_index);
} else {
switch (property_index) {
case kLookupInPrototype: {
Object* pt = holder_handle->GetPrototype();
*attributes = ABSENT;
if (pt == Heap::null_value()) return Heap::undefined_value();
result = pt->GetPropertyWithReceiver(
*receiver_handle,
*name_handle,
attributes);
RETURN_IF_SCHEDULED_EXCEPTION();
}
break;
case kLookupInHolder:
result = holder_handle->GetPropertyPostInterceptor(
*receiver_handle,
*name_handle,
attributes);
RETURN_IF_SCHEDULED_EXCEPTION();
break;
default:
UNREACHABLE();
}
}
return result;
}
Object* JSObject::GetPropertyWithInterceptor(
JSObject* receiver,
String* name,
PropertyAttributes* attributes) {
HandleScope scope;
Handle<JSObject> receiver_handle(receiver);
Handle<JSObject> holder_handle(this);
Handle<String> name_handle(name);
Object* result = NULL;
if (GetPropertyWithInterceptorProper(receiver, name, attributes, &result)) {
return result;
} else {
RETURN_IF_SCHEDULED_EXCEPTION();
}
result = holder_handle->GetPropertyPostInterceptor(
*receiver_handle,
*name_handle,
attributes);
RETURN_IF_SCHEDULED_EXCEPTION();
return raw_result;
return result;
}
......
......@@ -1349,6 +1349,14 @@ class JSObject: public HeapObject {
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);
......@@ -1540,6 +1548,14 @@ class JSObject: public HeapObject {
void LookupInDescriptor(String* name, LookupResult* result);
// Attempts to get property with a named interceptor getter. Returns
// |true| and stores result into |result| if succesful, otherwise
// returns |false|
bool GetPropertyWithInterceptorProper(JSObject* receiver,
String* name,
PropertyAttributes* attributes,
Object** result);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
};
......
......@@ -719,10 +719,12 @@ Object* LoadInterceptorProperty(Arguments args) {
JSObject* recv = JSObject::cast(args[0]);
JSObject* holder = JSObject::cast(args[1]);
String* name = String::cast(args[2]);
Smi* lookup_hint = Smi::cast(args[3]);
ASSERT(holder->HasNamedInterceptor());
PropertyAttributes attr = NONE;
Object* result = holder->GetPropertyWithInterceptor(recv, name, &attr);
Object* result = holder->GetInterceptorPropertyWithLookupHint(
recv, lookup_hint, name, &attr);
if (result->IsFailure()) return result;
// If the property is present, return it.
......
......@@ -351,6 +351,7 @@ class StubCompiler BASE_EMBEDDED {
static void GenerateLoadInterceptor(MacroAssembler* masm,
JSObject* object,
JSObject* holder,
Smi* lookup_hint,
Register receiver,
Register name,
Register scratch1,
......
......@@ -4827,6 +4827,23 @@ THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
}
typedef v8::Handle<Value> (*NamedPropertyGetter)(Local<String> property,
const AccessorInfo& info);
static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
const char* source,
int expected) {
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
templ->SetNamedPropertyHandler(getter);
LocalContext context;
context->Global()->Set(v8_str("o"), templ->NewInstance());
v8::Handle<Value> value = CompileRun(source);
CHECK_EQ(expected, value->Int32Value());
}
static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
const AccessorInfo& info) {
ApiTestFuzzer::Fuzz();
......@@ -4837,17 +4854,100 @@ static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
// This test should hit the load IC for the interceptor case.
THREADED_TEST(InterceptorLoadIC) {
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
templ->SetNamedPropertyHandler(InterceptorLoadICGetter);
LocalContext context;
context->Global()->Set(v8_str("o"), templ->NewInstance());
v8::Handle<Value> value = CompileRun(
CheckInterceptorLoadIC(InterceptorLoadICGetter,
"var result = 0;"
"for (var i = 0; i < 1000; i++) {"
" result = o.x;"
"}");
CHECK_EQ(42, value->Int32Value());
"}",
42);
}
// 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>();
}
THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
CheckInterceptorLoadIC(InterceptorLoadXICGetter,
"var result = 0;"
"o.y = 239;"
"for (var i = 0; i < 1000; i++) {"
" result = o.y;"
"}",
239);
}
THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
CheckInterceptorLoadIC(InterceptorLoadXICGetter,
"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(InterceptorLoadXICGetter,
"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(InterceptorLoadXICGetter,
"var result = 0;"
"for (var i = 0; i < 1000; i++) {"
" result = (o.y == undefined) ? 239 : 42;"
"}",
239);
}
THREADED_TEST(InterceptorLoadICWithOverride) {
CheckInterceptorLoadIC(InterceptorLoadXICGetter,
"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> InterceptorLoadICGetter0(Local<String> name,
const AccessorInfo& info) {
ApiTestFuzzer::Fuzz();
CHECK(v8_str("x")->Equals(name));
return v8::Integer::New(0);
}
THREADED_TEST(InterceptorReturningZero) {
CheckInterceptorLoadIC(InterceptorLoadICGetter0,
"o.x == undefined ? 1 : 0",
0);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment