Commit 0d2c8158 authored by antonm@chromium.org's avatar antonm@chromium.org

Compile precanned answers for the case of failed interceptor for some combinations.

Review URL: http://codereview.chromium.org/140069

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2577 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent cd16b5be
......@@ -483,7 +483,7 @@ void StubCompiler::GenerateLoadCallback(JSObject* object,
void StubCompiler::GenerateLoadInterceptor(JSObject* object,
JSObject* holder,
Smi* lookup_hint,
LookupResult* lookup,
Register receiver,
Register name_reg,
Register scratch1,
......@@ -502,8 +502,6 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
__ push(receiver); // receiver
__ push(reg); // holder
__ push(name_reg); // name
__ mov(scratch1, Operand(lookup_hint));
__ push(scratch1);
InterceptorInfo* interceptor = holder->GetNamedInterceptor();
ASSERT(!Heap::InNewSpace(interceptor));
......@@ -514,8 +512,8 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
// Do tail-call to the runtime system.
ExternalReference load_ic_property =
ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
__ TailCallRuntime(load_ic_property, 6);
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
__ TailCallRuntime(load_ic_property, 5);
}
......@@ -1059,9 +1057,11 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
__ ldr(r0, MemOperand(sp, 0));
LookupResult lookup;
holder->LocalLookupRealNamedProperty(name, &lookup);
GenerateLoadInterceptor(object,
holder,
holder->InterceptorPropertyLookupHint(name),
&lookup,
r0,
r2,
r3,
......@@ -1218,9 +1218,11 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ cmp(r2, Operand(Handle<String>(name)));
__ b(ne, &miss);
LookupResult lookup;
holder->LocalLookupRealNamedProperty(name, &lookup);
GenerateLoadInterceptor(receiver,
holder,
Smi::FromInt(JSObject::kLookupInHolder),
&lookup,
r0,
r2,
r3,
......
......@@ -1411,6 +1411,12 @@ bool Heap::CreateInitialObjects() {
if (obj->IsFailure()) return false;
set_the_hole_value(obj);
obj = CreateOddball(
oddball_map(), "no_interceptor_result_sentinel", Smi::FromInt(-2));
if (obj->IsFailure()) return false;
set_no_interceptor_result_sentinel(obj);
// Allocate the empty string.
obj = AllocateRawAsciiString(0, TENURED);
if (obj->IsFailure()) return false;
......
......@@ -110,6 +110,7 @@ namespace internal {
V(Map, two_pointer_filler_map, TwoPointerFillerMap) \
V(Object, nan_value, NanValue) \
V(Object, undefined_value, UndefinedValue) \
V(Object, no_interceptor_result_sentinel, NoInterceptorResultSentinel) \
V(Object, minus_zero_value, MinusZeroValue) \
V(Object, null_value, NullValue) \
V(Object, true_value, TrueValue) \
......
This diff is collapsed.
......@@ -35,17 +35,19 @@ namespace internal {
// IC_UTIL_LIST defines all utility functions called from generated
// inline caching code. The argument for the macro, ICU, is the function name.
#define IC_UTIL_LIST(ICU) \
ICU(LoadIC_Miss) \
ICU(KeyedLoadIC_Miss) \
ICU(CallIC_Miss) \
ICU(StoreIC_Miss) \
ICU(SharedStoreIC_ExtendStorage) \
ICU(KeyedStoreIC_Miss) \
/* Utilities for IC stubs. */ \
ICU(LoadCallbackProperty) \
ICU(StoreCallbackProperty) \
ICU(LoadInterceptorProperty) \
#define IC_UTIL_LIST(ICU) \
ICU(LoadIC_Miss) \
ICU(KeyedLoadIC_Miss) \
ICU(CallIC_Miss) \
ICU(StoreIC_Miss) \
ICU(SharedStoreIC_ExtendStorage) \
ICU(KeyedStoreIC_Miss) \
/* Utilities for IC stubs. */ \
ICU(LoadCallbackProperty) \
ICU(StoreCallbackProperty) \
ICU(LoadPropertyWithInterceptorOnly) \
ICU(LoadPropertyWithInterceptorForLoad) \
ICU(LoadPropertyWithInterceptorForCall) \
ICU(StoreInterceptorProperty)
//
......
......@@ -698,7 +698,7 @@ void Oddball::OddballVerify() {
} else {
ASSERT(number->IsSmi());
int value = Smi::cast(number)->value();
ASSERT(value == 0 || value == 1 || value == -1);
ASSERT(value == 0 || value == 1 || value == -1 || value == -2);
}
}
......
......@@ -2729,24 +2729,6 @@ 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);
}
......
......@@ -1507,10 +1507,6 @@ class JSObject: public HeapObject {
Object* LookupCallbackSetterInPrototypes(uint32_t index);
void LookupCallback(String* name, LookupResult* result);
inline Smi* InterceptorPropertyLookupHint(String* name);
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);
......
......@@ -787,23 +787,25 @@ Object* StoreCallbackProperty(Arguments args) {
return *value;
}
Object* LoadInterceptorProperty(Arguments args) {
/**
* Attempts to load a property with an interceptor (which must be present),
* but doesn't search the prototype chain.
*
* Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
* provide any value for the given name.
*/
Object* LoadPropertyWithInterceptorOnly(Arguments args) {
Handle<JSObject> receiver_handle = args.at<JSObject>(0);
Handle<JSObject> holder_handle = args.at<JSObject>(1);
Handle<String> name_handle = args.at<String>(2);
Smi* lookup_hint = Smi::cast(args[3]);
Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(4);
Handle<Object> data_handle = args.at<Object>(5);
Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(3);
Handle<Object> data_handle = args.at<Object>(4);
Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
v8::NamedPropertyGetter getter =
FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
ASSERT(getter != NULL);
PropertyAttributes attributes = ABSENT;
Object* result = Heap::undefined_value();
{
// Use the interceptor getter.
v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle),
......@@ -822,65 +824,92 @@ Object* LoadInterceptorProperty(Arguments args) {
}
}
int property_index = lookup_hint->value();
if (property_index >= 0) {
result = holder_handle->FastPropertyAt(property_index);
} else {
switch (property_index) {
case JSObject::kLookupInPrototype: {
Object* pt = holder_handle->GetPrototype();
if (pt == Heap::null_value()) return Heap::undefined_value();
result = pt->GetPropertyWithReceiver(
*receiver_handle,
*name_handle,
&attributes);
RETURN_IF_SCHEDULED_EXCEPTION();
}
break;
case JSObject::kLookupInHolder:
result = holder_handle->GetPropertyPostInterceptor(
*receiver_handle,
*name_handle,
&attributes);
RETURN_IF_SCHEDULED_EXCEPTION();
break;
default:
UNREACHABLE();
}
}
return Heap::no_interceptor_result_sentinel();
}
if (result->IsFailure()) return result;
if (attributes != ABSENT) return result;
// If the top frame is an internal frame, this is really a call
// IC. In this case, we simply return the undefined result which
// will lead to an exception when trying to invoke the result as a
// function.
StackFrameIterator it;
it.Advance(); // skip exit frame
if (it.frame()->is_internal()) return result;
static Object* ThrowReferenceError(String* name) {
// If the load is non-contextual, just return the undefined result.
// Note that both keyed and non-keyed loads may end up here, so we
// can't use either LoadIC or KeyedLoadIC constructors.
IC ic(IC::NO_EXTRA_FRAME);
ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
if (!ic.is_contextual()) return result;
if (!ic.is_contextual()) return Heap::undefined_value();
// Throw a reference error.
HandleScope scope;
Handle<String> name_handle(name);
Handle<Object> error =
Factory::NewReferenceError("not_defined",
HandleVector(&name_handle, 1));
return Top::Throw(*error);
}
static Object* LoadWithInterceptor(Arguments* args,
PropertyAttributes* attrs) {
Handle<JSObject> receiver_handle = args->at<JSObject>(0);
Handle<JSObject> holder_handle = args->at<JSObject>(1);
Handle<String> name_handle = args->at<String>(2);
Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(3);
Handle<Object> data_handle = args->at<Object>(4);
Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
v8::NamedPropertyGetter getter =
FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
ASSERT(getter != NULL);
{
// Use the interceptor getter.
v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle),
v8::Utils::ToLocal(data_handle),
v8::Utils::ToLocal(holder_handle));
HandleScope scope;
// We cannot use the raw name pointer here since getting the
// property might cause a GC. However, we can get the name from
// the stack using the arguments object.
Handle<String> name_handle = args.at<String>(2);
Handle<Object> error =
Factory::NewReferenceError("not_defined",
HandleVector(&name_handle, 1));
return Top::Throw(*error);
v8::Handle<v8::Value> r;
{
// Leaving JavaScript.
VMState state(EXTERNAL);
r = getter(v8::Utils::ToLocal(name_handle), info);
}
RETURN_IF_SCHEDULED_EXCEPTION();
if (!r.IsEmpty()) {
*attrs = NONE;
return *v8::Utils::OpenHandle(*r);
}
}
Object* result = holder_handle->GetPropertyPostInterceptor(
*receiver_handle,
*name_handle,
attrs);
RETURN_IF_SCHEDULED_EXCEPTION();
return result;
}
/**
* Loads a property with an interceptor performing post interceptor
* lookup if interceptor failed.
*/
Object* LoadPropertyWithInterceptorForLoad(Arguments args) {
PropertyAttributes attr = NONE;
Object* result = LoadWithInterceptor(&args, &attr);
if (result->IsFailure()) return result;
// If the property is present, return it.
if (attr != ABSENT) return result;
return ThrowReferenceError(String::cast(args[2]));
}
Object* LoadPropertyWithInterceptorForCall(Arguments args) {
PropertyAttributes attr;
Object* result = LoadWithInterceptor(&args, &attr);
RETURN_IF_SCHEDULED_EXCEPTION();
// This is call IC. In this case, we simply return the undefined result which
// will lead to an exception when trying to invoke the result as a
// function.
return result;
}
......
......@@ -307,7 +307,9 @@ Object* StoreCallbackProperty(Arguments args);
// Support functions for IC stubs for interceptors.
Object* LoadInterceptorProperty(Arguments args);
Object* LoadPropertyWithInterceptorOnly(Arguments args);
Object* LoadPropertyWithInterceptorForLoad(Arguments args);
Object* LoadPropertyWithInterceptorForCall(Arguments args);
Object* StoreInterceptorProperty(Arguments args);
Object* CallInterceptorProperty(Arguments args);
......@@ -377,13 +379,6 @@ class StubCompiler BASE_EMBEDDED {
Label* miss_label);
static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
protected:
Object* GetCodeWithFlags(Code::Flags flags, const char* name);
Object* GetCodeWithFlags(Code::Flags flags, String* name);
MacroAssembler* masm() { return &masm_; }
void set_failure(Failure* failure) { failure_ = failure; }
// Check the integrity of the prototype chain to make sure that the
// current IC is still valid.
Register CheckPrototypes(JSObject* object,
......@@ -394,6 +389,13 @@ class StubCompiler BASE_EMBEDDED {
String* name,
Label* miss);
protected:
Object* GetCodeWithFlags(Code::Flags flags, const char* name);
Object* GetCodeWithFlags(Code::Flags flags, String* name);
MacroAssembler* masm() { return &masm_; }
void set_failure(Failure* failure) { failure_ = failure; }
void GenerateLoadField(JSObject* object,
JSObject* holder,
Register receiver,
......@@ -424,7 +426,7 @@ class StubCompiler BASE_EMBEDDED {
void GenerateLoadInterceptor(JSObject* object,
JSObject* holder,
Smi* lookup_hint,
LookupResult* lookup,
Register receiver,
Register name_reg,
Register scratch1,
......
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