Handlify upper layers of LoadIC.
BUG= TEST= Review URL: http://codereview.chromium.org/8337008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9680 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
24bc70b2fb
commit
feeb0b0211
@ -3093,7 +3093,13 @@ static Local<Value> GetPropertyByLookup(i::Isolate* isolate,
|
|||||||
// If the property being looked up is a callback, it can throw
|
// If the property being looked up is a callback, it can throw
|
||||||
// an exception.
|
// an exception.
|
||||||
EXCEPTION_PREAMBLE(isolate);
|
EXCEPTION_PREAMBLE(isolate);
|
||||||
i::Handle<i::Object> result = i::GetProperty(receiver, name, lookup);
|
PropertyAttributes attributes;
|
||||||
|
i::Handle<i::Object> result = i::Object::GetProperty(isolate,
|
||||||
|
receiver,
|
||||||
|
receiver,
|
||||||
|
lookup,
|
||||||
|
name,
|
||||||
|
&attributes);
|
||||||
has_pending_exception = result.is_null();
|
has_pending_exception = result.is_null();
|
||||||
EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
|
EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
|
||||||
|
|
||||||
|
@ -376,17 +376,6 @@ Handle<Object> GetProperty(Handle<Object> obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Object> GetProperty(Handle<JSReceiver> obj,
|
|
||||||
Handle<String> name,
|
|
||||||
LookupResult* result) {
|
|
||||||
PropertyAttributes attributes;
|
|
||||||
Isolate* isolate = Isolate::Current();
|
|
||||||
CALL_HEAP_FUNCTION(isolate,
|
|
||||||
obj->GetProperty(*obj, result, *name, &attributes),
|
|
||||||
Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Object> GetElement(Handle<Object> obj,
|
Handle<Object> GetElement(Handle<Object> obj,
|
||||||
uint32_t index) {
|
uint32_t index) {
|
||||||
Isolate* isolate = Isolate::Current();
|
Isolate* isolate = Isolate::Current();
|
||||||
|
@ -246,11 +246,6 @@ Handle<Object> GetProperty(Handle<JSReceiver> obj,
|
|||||||
Handle<Object> GetProperty(Handle<Object> obj,
|
Handle<Object> GetProperty(Handle<Object> obj,
|
||||||
Handle<Object> key);
|
Handle<Object> key);
|
||||||
|
|
||||||
Handle<Object> GetProperty(Handle<JSReceiver> obj,
|
|
||||||
Handle<String> name,
|
|
||||||
LookupResult* result);
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Object> GetElement(Handle<Object> obj,
|
Handle<Object> GetElement(Handle<Object> obj,
|
||||||
uint32_t index);
|
uint32_t index);
|
||||||
|
|
||||||
|
209
src/ic.cc
209
src/ic.cc
@ -371,8 +371,7 @@ static bool HasInterceptorGetter(JSObject* object) {
|
|||||||
static void LookupForRead(Object* object,
|
static void LookupForRead(Object* object,
|
||||||
String* name,
|
String* name,
|
||||||
LookupResult* lookup) {
|
LookupResult* lookup) {
|
||||||
AssertNoAllocation no_gc; // pointers must stay valid
|
AssertNoAllocation no_gc;
|
||||||
|
|
||||||
// Skip all the objects with named interceptors, but
|
// Skip all the objects with named interceptors, but
|
||||||
// without actual getter.
|
// without actual getter.
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -408,6 +407,44 @@ static void LookupForRead(Object* object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void LookupForRead(Handle<Object> object,
|
||||||
|
Handle<String> name,
|
||||||
|
LookupResult* lookup) {
|
||||||
|
// Skip all the objects with named interceptors, but
|
||||||
|
// without actual getter.
|
||||||
|
while (true) {
|
||||||
|
object->Lookup(*name, lookup);
|
||||||
|
// Besides normal conditions (property not found or it's not
|
||||||
|
// an interceptor), bail out if lookup is not cacheable: we won't
|
||||||
|
// be able to IC it anyway and regular lookup should work fine.
|
||||||
|
if (!lookup->IsFound()
|
||||||
|
|| (lookup->type() != INTERCEPTOR)
|
||||||
|
|| !lookup->IsCacheable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<JSObject> holder(lookup->holder());
|
||||||
|
if (HasInterceptorGetter(*holder)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
holder->LocalLookupRealNamedProperty(*name, lookup);
|
||||||
|
if (lookup->IsProperty()) {
|
||||||
|
ASSERT(lookup->type() != INTERCEPTOR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<Object> proto(holder->GetPrototype());
|
||||||
|
if (proto->IsNull()) {
|
||||||
|
lookup->NotFound();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
object = proto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Object* CallICBase::TryCallAsFunction(Object* object) {
|
Object* CallICBase::TryCallAsFunction(Object* object) {
|
||||||
HandleScope scope(isolate());
|
HandleScope scope(isolate());
|
||||||
Handle<Object> target(object, isolate());
|
Handle<Object> target(object, isolate());
|
||||||
@ -850,53 +887,44 @@ MaybeObject* LoadIC::Load(State state,
|
|||||||
// the underlying string value. See ECMA-262 15.5.5.1.
|
// the underlying string value. See ECMA-262 15.5.5.1.
|
||||||
if ((object->IsString() || object->IsStringWrapper()) &&
|
if ((object->IsString() || object->IsStringWrapper()) &&
|
||||||
name->Equals(isolate()->heap()->length_symbol())) {
|
name->Equals(isolate()->heap()->length_symbol())) {
|
||||||
AssertNoAllocation no_allocation;
|
Handle<Code> stub;
|
||||||
Code* stub = NULL;
|
|
||||||
if (state == UNINITIALIZED) {
|
if (state == UNINITIALIZED) {
|
||||||
stub = pre_monomorphic_stub();
|
stub = pre_monomorphic_stub();
|
||||||
} else if (state == PREMONOMORPHIC) {
|
} else if (state == PREMONOMORPHIC) {
|
||||||
if (object->IsString()) {
|
stub = object->IsString()
|
||||||
stub = isolate()->builtins()->builtin(
|
? isolate()->builtins()->LoadIC_StringLength()
|
||||||
Builtins::kLoadIC_StringLength);
|
: isolate()->builtins()->LoadIC_StringWrapperLength();
|
||||||
} else {
|
|
||||||
stub = isolate()->builtins()->builtin(
|
|
||||||
Builtins::kLoadIC_StringWrapperLength);
|
|
||||||
}
|
|
||||||
} else if (state == MONOMORPHIC && object->IsStringWrapper()) {
|
} else if (state == MONOMORPHIC && object->IsStringWrapper()) {
|
||||||
stub = isolate()->builtins()->builtin(
|
stub = isolate()->builtins()->LoadIC_StringWrapperLength();
|
||||||
Builtins::kLoadIC_StringWrapperLength);
|
|
||||||
} else if (state != MEGAMORPHIC) {
|
} else if (state != MEGAMORPHIC) {
|
||||||
stub = megamorphic_stub();
|
stub = megamorphic_stub();
|
||||||
}
|
}
|
||||||
if (stub != NULL) {
|
if (!stub.is_null()) {
|
||||||
set_target(stub);
|
set_target(*stub);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
|
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// Get the string if we have a string wrapper object.
|
// Get the string if we have a string wrapper object.
|
||||||
if (object->IsJSValue()) {
|
Handle<Object> string = object->IsJSValue()
|
||||||
return Smi::FromInt(
|
? Handle<Object>(Handle<JSValue>::cast(object)->value())
|
||||||
String::cast(Handle<JSValue>::cast(object)->value())->length());
|
: object;
|
||||||
}
|
return Smi::FromInt(String::cast(*string)->length());
|
||||||
return Smi::FromInt(String::cast(*object)->length());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use specialized code for getting the length of arrays.
|
// Use specialized code for getting the length of arrays.
|
||||||
if (object->IsJSArray() &&
|
if (object->IsJSArray() &&
|
||||||
name->Equals(isolate()->heap()->length_symbol())) {
|
name->Equals(isolate()->heap()->length_symbol())) {
|
||||||
AssertNoAllocation no_allocation;
|
Handle<Code> stub;
|
||||||
Code* stub = NULL;
|
|
||||||
if (state == UNINITIALIZED) {
|
if (state == UNINITIALIZED) {
|
||||||
stub = pre_monomorphic_stub();
|
stub = pre_monomorphic_stub();
|
||||||
} else if (state == PREMONOMORPHIC) {
|
} else if (state == PREMONOMORPHIC) {
|
||||||
stub = isolate()->builtins()->builtin(
|
stub = isolate()->builtins()->LoadIC_ArrayLength();
|
||||||
Builtins::kLoadIC_ArrayLength);
|
|
||||||
} else if (state != MEGAMORPHIC) {
|
} else if (state != MEGAMORPHIC) {
|
||||||
stub = megamorphic_stub();
|
stub = megamorphic_stub();
|
||||||
}
|
}
|
||||||
if (stub != NULL) {
|
if (!stub.is_null()) {
|
||||||
set_target(stub);
|
set_target(*stub);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
|
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
|
||||||
#endif
|
#endif
|
||||||
@ -907,23 +935,20 @@ MaybeObject* LoadIC::Load(State state,
|
|||||||
// Use specialized code for getting prototype of functions.
|
// Use specialized code for getting prototype of functions.
|
||||||
if (object->IsJSFunction() &&
|
if (object->IsJSFunction() &&
|
||||||
name->Equals(isolate()->heap()->prototype_symbol()) &&
|
name->Equals(isolate()->heap()->prototype_symbol()) &&
|
||||||
JSFunction::cast(*object)->should_have_prototype()) {
|
Handle<JSFunction>::cast(object)->should_have_prototype()) {
|
||||||
{ AssertNoAllocation no_allocation;
|
Handle<Code> stub;
|
||||||
Code* stub = NULL;
|
if (state == UNINITIALIZED) {
|
||||||
if (state == UNINITIALIZED) {
|
stub = pre_monomorphic_stub();
|
||||||
stub = pre_monomorphic_stub();
|
} else if (state == PREMONOMORPHIC) {
|
||||||
} else if (state == PREMONOMORPHIC) {
|
stub = isolate()->builtins()->LoadIC_FunctionPrototype();
|
||||||
stub = isolate()->builtins()->builtin(
|
} else if (state != MEGAMORPHIC) {
|
||||||
Builtins::kLoadIC_FunctionPrototype);
|
stub = megamorphic_stub();
|
||||||
} else if (state != MEGAMORPHIC) {
|
}
|
||||||
stub = megamorphic_stub();
|
if (!stub.is_null()) {
|
||||||
}
|
set_target(*stub);
|
||||||
if (stub != NULL) {
|
|
||||||
set_target(stub);
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
|
if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Accessors::FunctionGetPrototype(*object, 0);
|
return Accessors::FunctionGetPrototype(*object, 0);
|
||||||
}
|
}
|
||||||
@ -936,7 +961,7 @@ MaybeObject* LoadIC::Load(State state,
|
|||||||
|
|
||||||
// Named lookup in the object.
|
// Named lookup in the object.
|
||||||
LookupResult lookup(isolate());
|
LookupResult lookup(isolate());
|
||||||
LookupForRead(*object, *name, &lookup);
|
LookupForRead(object, name, &lookup);
|
||||||
|
|
||||||
// If we did not find a property, check if we need to throw an exception.
|
// If we did not find a property, check if we need to throw an exception.
|
||||||
if (!lookup.IsProperty()) {
|
if (!lookup.IsProperty()) {
|
||||||
@ -955,17 +980,15 @@ MaybeObject* LoadIC::Load(State state,
|
|||||||
if (lookup.IsProperty() &&
|
if (lookup.IsProperty() &&
|
||||||
(lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
|
(lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
|
||||||
// Get the property.
|
// Get the property.
|
||||||
Object* result;
|
Handle<Object> result =
|
||||||
{ MaybeObject* maybe_result =
|
Object::GetProperty(isolate(), object, object, &lookup, name, &attr);
|
||||||
object->GetProperty(*object, &lookup, *name, &attr);
|
RETURN_IF_EMPTY_HANDLE(isolate(), result);
|
||||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
|
||||||
}
|
|
||||||
// If the property is not present, check if we need to throw an
|
// If the property is not present, check if we need to throw an
|
||||||
// exception.
|
// exception.
|
||||||
if (attr == ABSENT && IsContextual(object)) {
|
if (attr == ABSENT && IsContextual(object)) {
|
||||||
return ReferenceError("not_defined", name);
|
return ReferenceError("not_defined", name);
|
||||||
}
|
}
|
||||||
return result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the property.
|
// Get the property.
|
||||||
@ -988,91 +1011,75 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
|
|||||||
if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
|
if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
|
||||||
|
|
||||||
// Compute the code stub for this load.
|
// Compute the code stub for this load.
|
||||||
MaybeObject* maybe_code = NULL;
|
Handle<Code> code;
|
||||||
Object* code;
|
|
||||||
if (state == UNINITIALIZED) {
|
if (state == UNINITIALIZED) {
|
||||||
// This is the first time we execute this inline cache.
|
// This is the first time we execute this inline cache.
|
||||||
// Set the target to the pre monomorphic stub to delay
|
// Set the target to the pre monomorphic stub to delay
|
||||||
// setting the monomorphic state.
|
// setting the monomorphic state.
|
||||||
maybe_code = pre_monomorphic_stub();
|
code = pre_monomorphic_stub();
|
||||||
} else if (!lookup->IsProperty()) {
|
} else if (!lookup->IsProperty()) {
|
||||||
// Nonexistent property. The result is undefined.
|
// Nonexistent property. The result is undefined.
|
||||||
maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name,
|
code = isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
|
||||||
*receiver);
|
|
||||||
} else {
|
} else {
|
||||||
// Compute monomorphic stub.
|
// Compute monomorphic stub.
|
||||||
|
Handle<JSObject> holder(lookup->holder());
|
||||||
switch (lookup->type()) {
|
switch (lookup->type()) {
|
||||||
case FIELD: {
|
case FIELD:
|
||||||
maybe_code = isolate()->stub_cache()->ComputeLoadField(
|
code = isolate()->stub_cache()->ComputeLoadField(
|
||||||
*name,
|
name, receiver, holder, lookup->GetFieldIndex());
|
||||||
*receiver,
|
|
||||||
lookup->holder(),
|
|
||||||
lookup->GetFieldIndex());
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case CONSTANT_FUNCTION: {
|
case CONSTANT_FUNCTION: {
|
||||||
Object* constant = lookup->GetConstantFunction();
|
Handle<Object> constant(lookup->GetConstantFunction());
|
||||||
maybe_code = isolate()->stub_cache()->ComputeLoadConstant(
|
code = isolate()->stub_cache()->ComputeLoadConstant(
|
||||||
*name, *receiver, lookup->holder(), constant);
|
name, receiver, holder, constant);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NORMAL: {
|
case NORMAL:
|
||||||
if (lookup->holder()->IsGlobalObject()) {
|
if (holder->IsGlobalObject()) {
|
||||||
GlobalObject* global = GlobalObject::cast(lookup->holder());
|
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
|
||||||
JSGlobalPropertyCell* cell =
|
Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
|
||||||
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
|
code = isolate()->stub_cache()->ComputeLoadGlobal(
|
||||||
maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name,
|
name, receiver, global, cell, lookup->IsDontDelete());
|
||||||
*receiver,
|
|
||||||
global,
|
|
||||||
cell,
|
|
||||||
lookup->IsDontDelete());
|
|
||||||
} else {
|
} else {
|
||||||
// There is only one shared stub for loading normalized
|
// There is only one shared stub for loading normalized
|
||||||
// properties. It does not traverse the prototype chain, so the
|
// properties. It does not traverse the prototype chain, so the
|
||||||
// property must be found in the receiver for the stub to be
|
// property must be found in the receiver for the stub to be
|
||||||
// applicable.
|
// applicable.
|
||||||
if (lookup->holder() != *receiver) return;
|
if (!holder.is_identical_to(receiver)) return;
|
||||||
maybe_code = isolate()->stub_cache()->ComputeLoadNormal();
|
code = isolate()->stub_cache()->ComputeLoadNormal();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case CALLBACKS: {
|
case CALLBACKS: {
|
||||||
if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
|
Handle<Object> callback_object(lookup->GetCallbackObject());
|
||||||
AccessorInfo* callback =
|
if (!callback_object->IsAccessorInfo()) return;
|
||||||
AccessorInfo::cast(lookup->GetCallbackObject());
|
Handle<AccessorInfo> callback =
|
||||||
|
Handle<AccessorInfo>::cast(callback_object);
|
||||||
if (v8::ToCData<Address>(callback->getter()) == 0) return;
|
if (v8::ToCData<Address>(callback->getter()) == 0) return;
|
||||||
maybe_code = isolate()->stub_cache()->ComputeLoadCallback(
|
code = isolate()->stub_cache()->ComputeLoadCallback(
|
||||||
*name, *receiver, lookup->holder(), callback);
|
name, receiver, holder, callback);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INTERCEPTOR: {
|
case INTERCEPTOR:
|
||||||
ASSERT(HasInterceptorGetter(lookup->holder()));
|
ASSERT(HasInterceptorGetter(*holder));
|
||||||
maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor(
|
code = isolate()->stub_cache()->ComputeLoadInterceptor(
|
||||||
*name, *receiver, lookup->holder());
|
name, receiver, holder);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're unable to compute the stub (not enough memory left), we
|
|
||||||
// simply avoid updating the caches.
|
|
||||||
if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
|
|
||||||
|
|
||||||
// Patch the call site depending on the state of the cache.
|
// Patch the call site depending on the state of the cache.
|
||||||
if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
|
if (state == UNINITIALIZED ||
|
||||||
|
state == PREMONOMORPHIC ||
|
||||||
state == MONOMORPHIC_PROTOTYPE_FAILURE) {
|
state == MONOMORPHIC_PROTOTYPE_FAILURE) {
|
||||||
set_target(Code::cast(code));
|
set_target(*code);
|
||||||
} else if (state == MONOMORPHIC) {
|
} else if (state == MONOMORPHIC) {
|
||||||
set_target(megamorphic_stub());
|
set_target(*megamorphic_stub());
|
||||||
} else if (state == MEGAMORPHIC) {
|
} else if (state == MEGAMORPHIC) {
|
||||||
// Cache code holding map should be consistent with
|
// Cache code holding map should be consistent with
|
||||||
// GenerateMonomorphicCacheProbe.
|
// GenerateMonomorphicCacheProbe.
|
||||||
Map* map = JSObject::cast(object->IsJSObject() ? *object :
|
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
|
||||||
object->GetPrototype())->map();
|
|
||||||
|
|
||||||
isolate()->stub_cache()->Set(*name, map, Code::cast(code));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -1101,7 +1108,8 @@ MaybeObject* KeyedLoadIC::ComputePolymorphicStub(
|
|||||||
handler_ics.Add(cached_stub);
|
handler_ics.Add(cached_stub);
|
||||||
}
|
}
|
||||||
Object* object;
|
Object* object;
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate());
|
||||||
|
KeyedLoadStubCompiler compiler(isolate());
|
||||||
MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps,
|
MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps,
|
||||||
&handler_ics);
|
&handler_ics);
|
||||||
if (!maybe_code->ToObject(&object)) return maybe_code;
|
if (!maybe_code->ToObject(&object)) return maybe_code;
|
||||||
@ -1808,7 +1816,8 @@ MaybeObject* KeyedStoreIC::ComputePolymorphicStub(
|
|||||||
transitioned_maps.Add(transitioned_map);
|
transitioned_maps.Add(transitioned_map);
|
||||||
}
|
}
|
||||||
Object* object;
|
Object* object;
|
||||||
KeyedStoreStubCompiler compiler(strict_mode);
|
HandleScope scope(isolate());
|
||||||
|
KeyedStoreStubCompiler compiler(isolate(), strict_mode);
|
||||||
MaybeObject* maybe_code = compiler.CompileStorePolymorphic(
|
MaybeObject* maybe_code = compiler.CompileStorePolymorphic(
|
||||||
receiver_maps, &handler_ics, &transitioned_maps);
|
receiver_maps, &handler_ics, &transitioned_maps);
|
||||||
if (!maybe_code->ToObject(&object)) return maybe_code;
|
if (!maybe_code->ToObject(&object)) return maybe_code;
|
||||||
@ -2052,7 +2061,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
|
|||||||
|
|
||||||
// Used from ic-<arch>.cc.
|
// Used from ic-<arch>.cc.
|
||||||
RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
|
RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
|
||||||
NoHandleAllocation na;
|
HandleScope scope(isolate);
|
||||||
ASSERT(args.length() == 2);
|
ASSERT(args.length() == 2);
|
||||||
LoadIC ic(isolate);
|
LoadIC ic(isolate);
|
||||||
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
|
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
|
||||||
|
10
src/ic.h
10
src/ic.h
@ -321,17 +321,15 @@ class LoadIC: public IC {
|
|||||||
Handle<String> name);
|
Handle<String> name);
|
||||||
|
|
||||||
// Stub accessors.
|
// Stub accessors.
|
||||||
Code* megamorphic_stub() {
|
Handle<Code> megamorphic_stub() {
|
||||||
return isolate()->builtins()->builtin(
|
return isolate()->builtins()->LoadIC_Megamorphic();
|
||||||
Builtins::kLoadIC_Megamorphic);
|
|
||||||
}
|
}
|
||||||
static Code* initialize_stub() {
|
static Code* initialize_stub() {
|
||||||
return Isolate::Current()->builtins()->builtin(
|
return Isolate::Current()->builtins()->builtin(
|
||||||
Builtins::kLoadIC_Initialize);
|
Builtins::kLoadIC_Initialize);
|
||||||
}
|
}
|
||||||
Code* pre_monomorphic_stub() {
|
Handle<Code> pre_monomorphic_stub() {
|
||||||
return isolate()->builtins()->builtin(
|
return isolate()->builtins()->LoadIC_PreMonomorphic();
|
||||||
Builtins::kLoadIC_PreMonomorphic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Clear(Address address, Code* target);
|
static void Clear(Address address, Code* target);
|
||||||
|
@ -528,6 +528,19 @@ bool JSObject::IsDirty() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Object> Object::GetProperty(Isolate* isolate,
|
||||||
|
Handle<Object> object,
|
||||||
|
Handle<Object> receiver,
|
||||||
|
LookupResult* result,
|
||||||
|
Handle<String> key,
|
||||||
|
PropertyAttributes* attributes) {
|
||||||
|
CALL_HEAP_FUNCTION(
|
||||||
|
isolate,
|
||||||
|
object->GetProperty(*receiver, result, *key, attributes),
|
||||||
|
Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* Object::GetProperty(Object* receiver,
|
MaybeObject* Object::GetProperty(Object* receiver,
|
||||||
LookupResult* result,
|
LookupResult* result,
|
||||||
String* name,
|
String* name,
|
||||||
@ -3117,6 +3130,15 @@ void NormalizedMapCache::Clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSObject::UpdateMapCodeCache(Isolate* isolate,
|
||||||
|
Handle<JSObject> object,
|
||||||
|
Handle<String> name,
|
||||||
|
Handle<Code> code) {
|
||||||
|
CALL_HEAP_FUNCTION_VOID(isolate,
|
||||||
|
object->UpdateMapCodeCache(*name, *code));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
|
MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
|
||||||
if (map()->is_shared()) {
|
if (map()->is_shared()) {
|
||||||
// Fast case maps are never marked as shared.
|
// Fast case maps are never marked as shared.
|
||||||
|
@ -912,10 +912,19 @@ class Object : public MaybeObject {
|
|||||||
Object* receiver,
|
Object* receiver,
|
||||||
String* key,
|
String* key,
|
||||||
PropertyAttributes* attributes);
|
PropertyAttributes* attributes);
|
||||||
|
|
||||||
|
static Handle<Object> GetProperty(Isolate* isolate,
|
||||||
|
Handle<Object> object,
|
||||||
|
Handle<Object> receiver,
|
||||||
|
LookupResult* result,
|
||||||
|
Handle<String> key,
|
||||||
|
PropertyAttributes* attributes);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
|
MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
|
||||||
LookupResult* result,
|
LookupResult* result,
|
||||||
String* key,
|
String* key,
|
||||||
PropertyAttributes* attributes);
|
PropertyAttributes* attributes);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
|
MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
|
||||||
JSReceiver* getter);
|
JSReceiver* getter);
|
||||||
|
|
||||||
@ -1835,6 +1844,11 @@ class JSObject: public JSReceiver {
|
|||||||
// dictionary. Returns the backing after conversion.
|
// dictionary. Returns the backing after conversion.
|
||||||
MUST_USE_RESULT MaybeObject* NormalizeElements();
|
MUST_USE_RESULT MaybeObject* NormalizeElements();
|
||||||
|
|
||||||
|
static void UpdateMapCodeCache(Isolate* isolate,
|
||||||
|
Handle<JSObject> object,
|
||||||
|
Handle<String> name,
|
||||||
|
Handle<Code> code);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
|
MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
|
||||||
|
|
||||||
// Transform slow named properties to fast variants.
|
// Transform slow named properties to fast variants.
|
||||||
|
@ -8069,7 +8069,8 @@ static void TrySettingInlineConstructStub(Isolate* isolate,
|
|||||||
prototype = Handle<Object>(function->instance_prototype(), isolate);
|
prototype = Handle<Object>(function->instance_prototype(), isolate);
|
||||||
}
|
}
|
||||||
if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
|
if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
|
||||||
ConstructStubCompiler compiler;
|
HandleScope scope(isolate);
|
||||||
|
ConstructStubCompiler compiler(isolate);
|
||||||
MaybeObject* code = compiler.CompileConstructStub(*function);
|
MaybeObject* code = compiler.CompileConstructStub(*function);
|
||||||
if (!code->IsFailure()) {
|
if (!code->IsFailure()) {
|
||||||
function->shared()->set_construct_stub(
|
function->shared()->set_construct_stub(
|
||||||
|
@ -109,8 +109,17 @@ Code* StubCache::Set(String* name, Map* map, Code* code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* StubCache::ComputeLoadNonexistent(String* name,
|
Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
|
||||||
JSObject* receiver) {
|
Handle<JSObject> object,
|
||||||
|
Handle<JSObject> last) {
|
||||||
|
CALL_HEAP_FUNCTION(isolate(),
|
||||||
|
CompileLoadNonexistent(*name, *object, *last),
|
||||||
|
Code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
|
||||||
|
Handle<JSObject> receiver) {
|
||||||
ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
|
ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
|
||||||
// If no global objects are present in the prototype chain, the load
|
// If no global objects are present in the prototype chain, the load
|
||||||
// nonexistent IC stub can be shared for all names for a given map
|
// nonexistent IC stub can be shared for all names for a given map
|
||||||
@ -118,173 +127,181 @@ MaybeObject* StubCache::ComputeLoadNonexistent(String* name,
|
|||||||
// there are global objects involved, we need to check global
|
// there are global objects involved, we need to check global
|
||||||
// property cells in the stub and therefore the stub will be
|
// property cells in the stub and therefore the stub will be
|
||||||
// specific to the name.
|
// specific to the name.
|
||||||
String* cache_name = heap()->empty_string();
|
Handle<String> cache_name = factory()->empty_string();
|
||||||
if (receiver->IsGlobalObject()) cache_name = name;
|
if (receiver->IsGlobalObject()) cache_name = name;
|
||||||
JSObject* last = receiver;
|
Handle<JSObject> last = receiver;
|
||||||
while (last->GetPrototype() != heap()->null_value()) {
|
while (last->GetPrototype() != heap()->null_value()) {
|
||||||
last = JSObject::cast(last->GetPrototype());
|
last = Handle<JSObject>(JSObject::cast(last->GetPrototype()));
|
||||||
if (last->IsGlobalObject()) cache_name = name;
|
if (last->IsGlobalObject()) cache_name = name;
|
||||||
}
|
}
|
||||||
// Compile the stub that is either shared for all names or
|
// Compile the stub that is either shared for all names or
|
||||||
// name specific if there are global objects involved.
|
// name specific if there are global objects involved.
|
||||||
Code::Flags flags =
|
Code::Flags flags =
|
||||||
Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
|
Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
|
||||||
Object* code = receiver->map()->FindInCodeCache(cache_name, flags);
|
Handle<Object> probe(receiver->map()->FindInCodeCache(*cache_name, flags));
|
||||||
if (code->IsUndefined()) {
|
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||||
LoadStubCompiler compiler;
|
|
||||||
{ MaybeObject* maybe_code =
|
LoadStubCompiler compiler(isolate_);
|
||||||
compiler.CompileLoadNonexistent(cache_name, receiver, last);
|
Handle<Code> code =
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
compiler.CompileLoadNonexistent(cache_name, receiver, last);
|
||||||
}
|
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *cache_name));
|
||||||
PROFILE(isolate_,
|
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *cache_name, *code));
|
||||||
CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
|
JSObject::UpdateMapCodeCache(isolate_, receiver, cache_name, code);
|
||||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, cache_name, Code::cast(code)));
|
|
||||||
Object* result;
|
|
||||||
{ MaybeObject* maybe_result =
|
|
||||||
receiver->UpdateMapCodeCache(cache_name, Code::cast(code));
|
|
||||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* StubCache::ComputeLoadField(String* name,
|
Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
|
||||||
JSObject* receiver,
|
Handle<JSObject> holder,
|
||||||
JSObject* holder,
|
int index,
|
||||||
|
Handle<String> name) {
|
||||||
|
CALL_HEAP_FUNCTION(isolate(),
|
||||||
|
CompileLoadField(*object, *holder, index, *name),
|
||||||
|
Code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
|
||||||
|
Handle<JSObject> receiver,
|
||||||
|
Handle<JSObject> holder,
|
||||||
int field_index) {
|
int field_index) {
|
||||||
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
|
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
|
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
|
||||||
if (code->IsUndefined()) {
|
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||||
LoadStubCompiler compiler;
|
|
||||||
{ MaybeObject* maybe_code =
|
LoadStubCompiler compiler(isolate_);
|
||||||
compiler.CompileLoadField(receiver, holder, field_index, name);
|
Handle<Code> code =
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
compiler.CompileLoadField(receiver, holder, field_index, name);
|
||||||
}
|
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||||
PROFILE(isolate_,
|
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||||
CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
|
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
|
||||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
|
|
||||||
Object* result;
|
|
||||||
{ MaybeObject* maybe_result =
|
|
||||||
receiver->UpdateMapCodeCache(name, Code::cast(code));
|
|
||||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* StubCache::ComputeLoadCallback(String* name,
|
Handle<Code> LoadStubCompiler::CompileLoadCallback(
|
||||||
JSObject* receiver,
|
Handle<String> name,
|
||||||
JSObject* holder,
|
Handle<JSObject> object,
|
||||||
AccessorInfo* callback) {
|
Handle<JSObject> holder,
|
||||||
|
Handle<AccessorInfo> callback) {
|
||||||
|
CALL_HEAP_FUNCTION(isolate(),
|
||||||
|
CompileLoadCallback(*name, *object, *holder, *callback),
|
||||||
|
Code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name,
|
||||||
|
Handle<JSObject> receiver,
|
||||||
|
Handle<JSObject> holder,
|
||||||
|
Handle<AccessorInfo> callback) {
|
||||||
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
|
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
|
||||||
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
|
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
|
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
|
||||||
if (code->IsUndefined()) {
|
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||||
LoadStubCompiler compiler;
|
|
||||||
{ MaybeObject* maybe_code =
|
LoadStubCompiler compiler(isolate_);
|
||||||
compiler.CompileLoadCallback(name, receiver, holder, callback);
|
Handle<Code> code =
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
compiler.CompileLoadCallback(name, receiver, holder, callback);
|
||||||
}
|
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||||
PROFILE(isolate_,
|
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||||
CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
|
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
|
||||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
|
|
||||||
Object* result;
|
|
||||||
{ MaybeObject* maybe_result =
|
|
||||||
receiver->UpdateMapCodeCache(name, Code::cast(code));
|
|
||||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* StubCache::ComputeLoadConstant(String* name,
|
Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
|
||||||
JSObject* receiver,
|
Handle<JSObject> holder,
|
||||||
JSObject* holder,
|
Handle<Object> value,
|
||||||
Object* value) {
|
Handle<String> name) {
|
||||||
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
|
CALL_HEAP_FUNCTION(isolate(),
|
||||||
|
CompileLoadConstant(*object, *holder, *value, *name),
|
||||||
|
Code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
|
||||||
|
Handle<JSObject> receiver,
|
||||||
|
Handle<JSObject> holder,
|
||||||
|
Handle<Object> value) {
|
||||||
|
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||||
Code::Flags flags =
|
Code::Flags flags =
|
||||||
Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
|
Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
|
||||||
if (code->IsUndefined()) {
|
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||||
LoadStubCompiler compiler;
|
|
||||||
{ MaybeObject* maybe_code =
|
LoadStubCompiler compiler(isolate_);
|
||||||
compiler.CompileLoadConstant(receiver, holder, value, name);
|
Handle<Code> code =
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
compiler.CompileLoadConstant(receiver, holder, value, name);
|
||||||
}
|
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||||
PROFILE(isolate_,
|
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||||
CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
|
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
|
||||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
|
|
||||||
Object* result;
|
|
||||||
{ MaybeObject* maybe_result =
|
|
||||||
receiver->UpdateMapCodeCache(name, Code::cast(code));
|
|
||||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* StubCache::ComputeLoadInterceptor(String* name,
|
Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object,
|
||||||
JSObject* receiver,
|
Handle<JSObject> holder,
|
||||||
JSObject* holder) {
|
Handle<String> name) {
|
||||||
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
|
CALL_HEAP_FUNCTION(isolate(),
|
||||||
|
CompileLoadInterceptor(*object, *holder, *name),
|
||||||
|
Code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
|
||||||
|
Handle<JSObject> receiver,
|
||||||
|
Handle<JSObject> holder) {
|
||||||
|
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
|
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
|
||||||
if (code->IsUndefined()) {
|
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||||
LoadStubCompiler compiler;
|
|
||||||
{ MaybeObject* maybe_code =
|
LoadStubCompiler compiler(isolate_);
|
||||||
compiler.CompileLoadInterceptor(receiver, holder, name);
|
Handle<Code> code =
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
compiler.CompileLoadInterceptor(receiver, holder, name);
|
||||||
}
|
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||||
PROFILE(isolate_,
|
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||||
CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
|
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
|
||||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
|
|
||||||
Object* result;
|
|
||||||
{ MaybeObject* maybe_result =
|
|
||||||
receiver->UpdateMapCodeCache(name, Code::cast(code));
|
|
||||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* StubCache::ComputeLoadNormal() {
|
Handle<Code> StubCache::ComputeLoadNormal() {
|
||||||
return isolate_->builtins()->builtin(Builtins::kLoadIC_Normal);
|
return isolate_->builtins()->LoadIC_Normal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
||||||
MaybeObject* StubCache::ComputeLoadGlobal(String* name,
|
Handle<JSObject> object,
|
||||||
JSObject* receiver,
|
Handle<GlobalObject> holder,
|
||||||
GlobalObject* holder,
|
Handle<JSGlobalPropertyCell> cell,
|
||||||
JSGlobalPropertyCell* cell,
|
Handle<String> name,
|
||||||
|
bool is_dont_delete) {
|
||||||
|
CALL_HEAP_FUNCTION(isolate(),
|
||||||
|
CompileLoadGlobal(*object,
|
||||||
|
*holder,
|
||||||
|
*cell,
|
||||||
|
*name,
|
||||||
|
is_dont_delete),
|
||||||
|
Code);
|
||||||
|
}
|
||||||
|
Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
|
||||||
|
Handle<JSObject> receiver,
|
||||||
|
Handle<GlobalObject> holder,
|
||||||
|
Handle<JSGlobalPropertyCell> cell,
|
||||||
bool is_dont_delete) {
|
bool is_dont_delete) {
|
||||||
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
|
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
|
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
|
||||||
if (code->IsUndefined()) {
|
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||||
LoadStubCompiler compiler;
|
|
||||||
{ MaybeObject* maybe_code = compiler.CompileLoadGlobal(receiver,
|
LoadStubCompiler compiler(isolate_);
|
||||||
holder,
|
Handle<Code> code =
|
||||||
cell,
|
compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
|
||||||
name,
|
PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
|
||||||
is_dont_delete);
|
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
|
||||||
}
|
|
||||||
PROFILE(isolate_,
|
|
||||||
CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
|
|
||||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
|
|
||||||
Object* result;
|
|
||||||
{ MaybeObject* maybe_result =
|
|
||||||
receiver->UpdateMapCodeCache(name, Code::cast(code));
|
|
||||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +314,8 @@ MaybeObject* StubCache::ComputeKeyedLoadField(String* name,
|
|||||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
|
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
KeyedLoadStubCompiler compiler(isolate_);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileLoadField(name, receiver, holder, field_index);
|
compiler.CompileLoadField(name, receiver, holder, field_index);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -324,7 +342,8 @@ MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name,
|
|||||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
|
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
KeyedLoadStubCompiler compiler(isolate_);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileLoadConstant(name, receiver, holder, value);
|
compiler.CompileLoadConstant(name, receiver, holder, value);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -350,7 +369,8 @@ MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name,
|
|||||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
|
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
KeyedLoadStubCompiler compiler(isolate_);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileLoadInterceptor(receiver, holder, name);
|
compiler.CompileLoadInterceptor(receiver, holder, name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -377,7 +397,8 @@ MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name,
|
|||||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
|
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
KeyedLoadStubCompiler compiler(isolate_);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileLoadCallback(name, receiver, holder, callback);
|
compiler.CompileLoadCallback(name, receiver, holder, callback);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -403,7 +424,8 @@ MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name,
|
|||||||
ASSERT(receiver->IsJSObject());
|
ASSERT(receiver->IsJSObject());
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
KeyedLoadStubCompiler compiler(isolate_);
|
||||||
{ MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
|
{ MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
}
|
}
|
||||||
@ -427,7 +449,8 @@ MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name,
|
|||||||
Map* map = receiver->map();
|
Map* map = receiver->map();
|
||||||
Object* code = map->FindInCodeCache(name, flags);
|
Object* code = map->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
KeyedLoadStubCompiler compiler(isolate_);
|
||||||
{ MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
|
{ MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
}
|
}
|
||||||
@ -450,7 +473,8 @@ MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype(
|
|||||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
|
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
KeyedLoadStubCompiler compiler(isolate_);
|
||||||
{ MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
|
{ MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
}
|
}
|
||||||
@ -477,7 +501,8 @@ MaybeObject* StubCache::ComputeStoreField(String* name,
|
|||||||
Code::STORE_IC, type, strict_mode);
|
Code::STORE_IC, type, strict_mode);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
StoreStubCompiler compiler(strict_mode);
|
HandleScope scope(isolate_);
|
||||||
|
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileStoreField(receiver, field_index, transition, name);
|
compiler.CompileStoreField(receiver, field_index, transition, name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -524,12 +549,14 @@ MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement(
|
|||||||
MaybeObject* maybe_new_code = NULL;
|
MaybeObject* maybe_new_code = NULL;
|
||||||
switch (stub_kind) {
|
switch (stub_kind) {
|
||||||
case KeyedIC::LOAD: {
|
case KeyedIC::LOAD: {
|
||||||
KeyedLoadStubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
KeyedLoadStubCompiler compiler(isolate_);
|
||||||
maybe_new_code = compiler.CompileLoadElement(receiver_map);
|
maybe_new_code = compiler.CompileLoadElement(receiver_map);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KeyedIC::STORE_NO_TRANSITION: {
|
case KeyedIC::STORE_NO_TRANSITION: {
|
||||||
KeyedStoreStubCompiler compiler(strict_mode);
|
HandleScope scope(isolate_);
|
||||||
|
KeyedStoreStubCompiler compiler(isolate_, strict_mode);
|
||||||
maybe_new_code = compiler.CompileStoreElement(receiver_map);
|
maybe_new_code = compiler.CompileStoreElement(receiver_map);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -574,7 +601,8 @@ MaybeObject* StubCache::ComputeStoreGlobal(String* name,
|
|||||||
Code::STORE_IC, NORMAL, strict_mode);
|
Code::STORE_IC, NORMAL, strict_mode);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
StoreStubCompiler compiler(strict_mode);
|
HandleScope scope(isolate_);
|
||||||
|
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileStoreGlobal(receiver, cell, name);
|
compiler.CompileStoreGlobal(receiver, cell, name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -602,7 +630,8 @@ MaybeObject* StubCache::ComputeStoreCallback(
|
|||||||
Code::STORE_IC, CALLBACKS, strict_mode);
|
Code::STORE_IC, CALLBACKS, strict_mode);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
StoreStubCompiler compiler(strict_mode);
|
HandleScope scope(isolate_);
|
||||||
|
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileStoreCallback(receiver, callback, name);
|
compiler.CompileStoreCallback(receiver, callback, name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -628,7 +657,8 @@ MaybeObject* StubCache::ComputeStoreInterceptor(
|
|||||||
Code::STORE_IC, INTERCEPTOR, strict_mode);
|
Code::STORE_IC, INTERCEPTOR, strict_mode);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
StoreStubCompiler compiler(strict_mode);
|
HandleScope scope(isolate_);
|
||||||
|
StoreStubCompiler compiler(isolate_, strict_mode);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileStoreInterceptor(receiver, name);
|
compiler.CompileStoreInterceptor(receiver, name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -656,7 +686,8 @@ MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
|
|||||||
Code::KEYED_STORE_IC, type, strict_mode);
|
Code::KEYED_STORE_IC, type, strict_mode);
|
||||||
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
Object* code = receiver->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
KeyedStoreStubCompiler compiler(strict_mode);
|
HandleScope scope(isolate());
|
||||||
|
KeyedStoreStubCompiler compiler(isolate(), strict_mode);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileStoreField(receiver, field_index, transition, name);
|
compiler.CompileStoreField(receiver, field_index, transition, name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -712,7 +743,12 @@ MaybeObject* StubCache::ComputeCallConstant(int argc,
|
|||||||
// caches.
|
// caches.
|
||||||
if (!function->is_compiled()) return Failure::InternalError();
|
if (!function->is_compiled()) return Failure::InternalError();
|
||||||
// Compile the stub - only create stubs for fully compiled functions.
|
// Compile the stub - only create stubs for fully compiled functions.
|
||||||
CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder);
|
HandleScope scope(isolate_);
|
||||||
|
CallStubCompiler compiler(isolate_,
|
||||||
|
argc,
|
||||||
|
kind,
|
||||||
|
extra_ic_state,
|
||||||
|
cache_holder);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileCallConstant(object, holder, function, name, check);
|
compiler.CompileCallConstant(object, holder, function, name, check);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -759,7 +795,12 @@ MaybeObject* StubCache::ComputeCallField(int argc,
|
|||||||
argc);
|
argc);
|
||||||
Object* code = map_holder->map()->FindInCodeCache(name, flags);
|
Object* code = map_holder->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder);
|
HandleScope scope(isolate_);
|
||||||
|
CallStubCompiler compiler(isolate_,
|
||||||
|
argc,
|
||||||
|
kind,
|
||||||
|
extra_ic_state,
|
||||||
|
cache_holder);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileCallField(JSObject::cast(object),
|
compiler.CompileCallField(JSObject::cast(object),
|
||||||
holder,
|
holder,
|
||||||
@ -808,7 +849,12 @@ MaybeObject* StubCache::ComputeCallInterceptor(
|
|||||||
argc);
|
argc);
|
||||||
Object* code = map_holder->map()->FindInCodeCache(name, flags);
|
Object* code = map_holder->map()->FindInCodeCache(name, flags);
|
||||||
if (code->IsUndefined()) {
|
if (code->IsUndefined()) {
|
||||||
CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder);
|
HandleScope scope(isolate());
|
||||||
|
CallStubCompiler compiler(isolate(),
|
||||||
|
argc,
|
||||||
|
kind,
|
||||||
|
extra_ic_state,
|
||||||
|
cache_holder);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileCallInterceptor(JSObject::cast(object), holder, name);
|
compiler.CompileCallInterceptor(JSObject::cast(object), holder, name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -864,7 +910,12 @@ MaybeObject* StubCache::ComputeCallGlobal(int argc,
|
|||||||
// internal error which will make sure we do not update any
|
// internal error which will make sure we do not update any
|
||||||
// caches.
|
// caches.
|
||||||
if (!function->is_compiled()) return Failure::InternalError();
|
if (!function->is_compiled()) return Failure::InternalError();
|
||||||
CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder);
|
HandleScope scope(isolate());
|
||||||
|
CallStubCompiler compiler(isolate(),
|
||||||
|
argc,
|
||||||
|
kind,
|
||||||
|
extra_ic_state,
|
||||||
|
cache_holder);
|
||||||
{ MaybeObject* maybe_code =
|
{ MaybeObject* maybe_code =
|
||||||
compiler.CompileCallGlobal(receiver, holder, cell, function, name);
|
compiler.CompileCallGlobal(receiver, holder, cell, function, name);
|
||||||
if (!maybe_code->ToObject(&code)) return maybe_code;
|
if (!maybe_code->ToObject(&code)) return maybe_code;
|
||||||
@ -967,7 +1018,8 @@ MaybeObject* StubCache::ComputeCallInitialize(int argc,
|
|||||||
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
||||||
}
|
}
|
||||||
if (!probe->IsUndefined()) return probe;
|
if (!probe->IsUndefined()) return probe;
|
||||||
StubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
StubCompiler compiler(isolate_);
|
||||||
return FillCache(isolate_, compiler.CompileCallInitialize(flags));
|
return FillCache(isolate_, compiler.CompileCallInitialize(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1002,7 +1054,8 @@ MaybeObject* StubCache::ComputeCallPreMonomorphic(
|
|||||||
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
||||||
}
|
}
|
||||||
if (!probe->IsUndefined()) return probe;
|
if (!probe->IsUndefined()) return probe;
|
||||||
StubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
StubCompiler compiler(isolate_);
|
||||||
return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
|
return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,7 +1073,8 @@ MaybeObject* StubCache::ComputeCallNormal(int argc,
|
|||||||
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
||||||
}
|
}
|
||||||
if (!probe->IsUndefined()) return probe;
|
if (!probe->IsUndefined()) return probe;
|
||||||
StubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
StubCompiler compiler(isolate_);
|
||||||
return FillCache(isolate_, compiler.CompileCallNormal(flags));
|
return FillCache(isolate_, compiler.CompileCallNormal(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1037,7 +1091,8 @@ MaybeObject* StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
|
|||||||
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
||||||
}
|
}
|
||||||
if (!probe->IsUndefined()) return probe;
|
if (!probe->IsUndefined()) return probe;
|
||||||
StubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
StubCompiler compiler(isolate_);
|
||||||
return FillCache(isolate_, compiler.CompileCallArguments(flags));
|
return FillCache(isolate_, compiler.CompileCallArguments(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1056,7 +1111,8 @@ MaybeObject* StubCache::ComputeCallMegamorphic(
|
|||||||
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
||||||
}
|
}
|
||||||
if (!probe->IsUndefined()) return probe;
|
if (!probe->IsUndefined()) return probe;
|
||||||
StubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
StubCompiler compiler(isolate_);
|
||||||
return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
|
return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1077,7 +1133,8 @@ MaybeObject* StubCache::ComputeCallMiss(int argc,
|
|||||||
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
||||||
}
|
}
|
||||||
if (!probe->IsUndefined()) return probe;
|
if (!probe->IsUndefined()) return probe;
|
||||||
StubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
StubCompiler compiler(isolate_);
|
||||||
return FillCache(isolate_, compiler.CompileCallMiss(flags));
|
return FillCache(isolate_, compiler.CompileCallMiss(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1098,7 +1155,8 @@ MaybeObject* StubCache::ComputeCallDebugBreak(
|
|||||||
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
||||||
}
|
}
|
||||||
if (!probe->IsUndefined()) return probe;
|
if (!probe->IsUndefined()) return probe;
|
||||||
StubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
StubCompiler compiler(isolate_);
|
||||||
return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
|
return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,7 +1176,8 @@ MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(
|
|||||||
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
||||||
}
|
}
|
||||||
if (!probe->IsUndefined()) return probe;
|
if (!probe->IsUndefined()) return probe;
|
||||||
StubCompiler compiler;
|
HandleScope scope(isolate_);
|
||||||
|
StubCompiler compiler(isolate_);
|
||||||
return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
|
return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1704,11 +1763,13 @@ void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CallStubCompiler::CallStubCompiler(int argc,
|
CallStubCompiler::CallStubCompiler(Isolate* isolate,
|
||||||
|
int argc,
|
||||||
Code::Kind kind,
|
Code::Kind kind,
|
||||||
Code::ExtraICState extra_ic_state,
|
Code::ExtraICState extra_ic_state,
|
||||||
InlineCacheHolderFlag cache_holder)
|
InlineCacheHolderFlag cache_holder)
|
||||||
: arguments_(argc),
|
: StubCompiler(isolate),
|
||||||
|
arguments_(argc),
|
||||||
kind_(kind),
|
kind_(kind),
|
||||||
extra_ic_state_(extra_ic_state),
|
extra_ic_state_(extra_ic_state),
|
||||||
cache_holder_(cache_holder) {
|
cache_holder_(cache_holder) {
|
||||||
|
106
src/stub-cache.h
106
src/stub-cache.h
@ -76,41 +76,35 @@ class StubCache {
|
|||||||
|
|
||||||
// Computes the right stub matching. Inserts the result in the
|
// Computes the right stub matching. Inserts the result in the
|
||||||
// cache before returning. This might compile a stub if needed.
|
// cache before returning. This might compile a stub if needed.
|
||||||
MUST_USE_RESULT MaybeObject* ComputeLoadNonexistent(
|
Handle<Code> ComputeLoadNonexistent(Handle<String> name,
|
||||||
String* name,
|
Handle<JSObject> receiver);
|
||||||
JSObject* receiver);
|
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* ComputeLoadField(String* name,
|
Handle<Code> ComputeLoadField(Handle<String> name,
|
||||||
JSObject* receiver,
|
Handle<JSObject> receiver,
|
||||||
JSObject* holder,
|
Handle<JSObject> holder,
|
||||||
int field_index);
|
int field_index);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* ComputeLoadCallback(
|
Handle<Code> ComputeLoadCallback(Handle<String> name,
|
||||||
String* name,
|
Handle<JSObject> receiver,
|
||||||
JSObject* receiver,
|
Handle<JSObject> holder,
|
||||||
JSObject* holder,
|
Handle<AccessorInfo> callback);
|
||||||
AccessorInfo* callback);
|
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* ComputeLoadConstant(String* name,
|
Handle<Code> ComputeLoadConstant(Handle<String> name,
|
||||||
JSObject* receiver,
|
Handle<JSObject> receiver,
|
||||||
JSObject* holder,
|
Handle<JSObject> holder,
|
||||||
Object* value);
|
Handle<Object> value);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* ComputeLoadInterceptor(
|
Handle<Code> ComputeLoadInterceptor(Handle<String> name,
|
||||||
String* name,
|
Handle<JSObject> receiver,
|
||||||
JSObject* receiver,
|
Handle<JSObject> holder);
|
||||||
JSObject* holder);
|
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* ComputeLoadNormal();
|
Handle<Code> ComputeLoadNormal();
|
||||||
|
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* ComputeLoadGlobal(
|
|
||||||
String* name,
|
|
||||||
JSObject* receiver,
|
|
||||||
GlobalObject* holder,
|
|
||||||
JSGlobalPropertyCell* cell,
|
|
||||||
bool is_dont_delete);
|
|
||||||
|
|
||||||
|
Handle<Code> ComputeLoadGlobal(Handle<String> name,
|
||||||
|
Handle<JSObject> receiver,
|
||||||
|
Handle<GlobalObject> holder,
|
||||||
|
Handle<JSGlobalPropertyCell> cell,
|
||||||
|
bool is_dont_delete);
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
@ -330,6 +324,7 @@ class StubCache {
|
|||||||
|
|
||||||
Isolate* isolate() { return isolate_; }
|
Isolate* isolate() { return isolate_; }
|
||||||
Heap* heap() { return isolate()->heap(); }
|
Heap* heap() { return isolate()->heap(); }
|
||||||
|
Factory* factory() { return isolate()->factory(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit StubCache(Isolate* isolate);
|
explicit StubCache(Isolate* isolate);
|
||||||
@ -410,8 +405,8 @@ DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
|
|||||||
// The stub compiler compiles stubs for the stub cache.
|
// The stub compiler compiles stubs for the stub cache.
|
||||||
class StubCompiler BASE_EMBEDDED {
|
class StubCompiler BASE_EMBEDDED {
|
||||||
public:
|
public:
|
||||||
StubCompiler()
|
explicit StubCompiler(Isolate* isolate)
|
||||||
: scope_(), masm_(Isolate::Current(), NULL, 256), failure_(NULL) { }
|
: isolate_(isolate), masm_(isolate, NULL, 256), failure_(NULL) { }
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
|
MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
|
||||||
MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
|
MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
|
||||||
@ -567,12 +562,12 @@ class StubCompiler BASE_EMBEDDED {
|
|||||||
String* name,
|
String* name,
|
||||||
LookupResult* lookup);
|
LookupResult* lookup);
|
||||||
|
|
||||||
Isolate* isolate() { return scope_.isolate(); }
|
Isolate* isolate() { return isolate_; }
|
||||||
Heap* heap() { return isolate()->heap(); }
|
Heap* heap() { return isolate()->heap(); }
|
||||||
Factory* factory() { return isolate()->factory(); }
|
Factory* factory() { return isolate()->factory(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HandleScope scope_;
|
Isolate* isolate_;
|
||||||
MacroAssembler masm_;
|
MacroAssembler masm_;
|
||||||
Failure* failure_;
|
Failure* failure_;
|
||||||
};
|
};
|
||||||
@ -580,29 +575,60 @@ class StubCompiler BASE_EMBEDDED {
|
|||||||
|
|
||||||
class LoadStubCompiler: public StubCompiler {
|
class LoadStubCompiler: public StubCompiler {
|
||||||
public:
|
public:
|
||||||
|
explicit LoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
|
||||||
|
|
||||||
|
Handle<Code> CompileLoadNonexistent(Handle<String> name,
|
||||||
|
Handle<JSObject> object,
|
||||||
|
Handle<JSObject> last);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
|
MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
|
||||||
JSObject* object,
|
JSObject* object,
|
||||||
JSObject* last);
|
JSObject* last);
|
||||||
|
|
||||||
|
Handle<Code> CompileLoadField(Handle<JSObject> object,
|
||||||
|
Handle<JSObject> holder,
|
||||||
|
int index,
|
||||||
|
Handle<String> name);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
|
MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
|
||||||
JSObject* holder,
|
JSObject* holder,
|
||||||
int index,
|
int index,
|
||||||
String* name);
|
String* name);
|
||||||
|
|
||||||
|
Handle<Code> CompileLoadCallback(Handle<String> name,
|
||||||
|
Handle<JSObject> object,
|
||||||
|
Handle<JSObject> holder,
|
||||||
|
Handle<AccessorInfo> callback);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
|
MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
|
||||||
JSObject* object,
|
JSObject* object,
|
||||||
JSObject* holder,
|
JSObject* holder,
|
||||||
AccessorInfo* callback);
|
AccessorInfo* callback);
|
||||||
|
|
||||||
|
Handle<Code> CompileLoadConstant(Handle<JSObject> object,
|
||||||
|
Handle<JSObject> holder,
|
||||||
|
Handle<Object> value,
|
||||||
|
Handle<String> name);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
|
MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
|
||||||
JSObject* holder,
|
JSObject* holder,
|
||||||
Object* value,
|
Object* value,
|
||||||
String* name);
|
String* name);
|
||||||
|
|
||||||
|
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
|
||||||
|
Handle<JSObject> holder,
|
||||||
|
Handle<String> name);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
|
MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
|
||||||
JSObject* holder,
|
JSObject* holder,
|
||||||
String* name);
|
String* name);
|
||||||
|
|
||||||
|
Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
|
||||||
|
Handle<GlobalObject> holder,
|
||||||
|
Handle<JSGlobalPropertyCell> cell,
|
||||||
|
Handle<String> name,
|
||||||
|
bool is_dont_delete);
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
|
MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
|
||||||
GlobalObject* holder,
|
GlobalObject* holder,
|
||||||
JSGlobalPropertyCell* cell,
|
JSGlobalPropertyCell* cell,
|
||||||
@ -616,6 +642,7 @@ class LoadStubCompiler: public StubCompiler {
|
|||||||
|
|
||||||
class KeyedLoadStubCompiler: public StubCompiler {
|
class KeyedLoadStubCompiler: public StubCompiler {
|
||||||
public:
|
public:
|
||||||
|
explicit KeyedLoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
|
||||||
MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
|
MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
|
||||||
JSObject* object,
|
JSObject* object,
|
||||||
JSObject* holder,
|
JSObject* holder,
|
||||||
@ -663,8 +690,8 @@ class KeyedLoadStubCompiler: public StubCompiler {
|
|||||||
|
|
||||||
class StoreStubCompiler: public StubCompiler {
|
class StoreStubCompiler: public StubCompiler {
|
||||||
public:
|
public:
|
||||||
explicit StoreStubCompiler(StrictModeFlag strict_mode)
|
StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
|
||||||
: strict_mode_(strict_mode) { }
|
: StubCompiler(isolate), strict_mode_(strict_mode) { }
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
|
MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
|
||||||
int index,
|
int index,
|
||||||
@ -690,8 +717,8 @@ class StoreStubCompiler: public StubCompiler {
|
|||||||
|
|
||||||
class KeyedStoreStubCompiler: public StubCompiler {
|
class KeyedStoreStubCompiler: public StubCompiler {
|
||||||
public:
|
public:
|
||||||
explicit KeyedStoreStubCompiler(StrictModeFlag strict_mode)
|
KeyedStoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
|
||||||
: strict_mode_(strict_mode) { }
|
: StubCompiler(isolate), strict_mode_(strict_mode) { }
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
|
MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
|
||||||
int index,
|
int index,
|
||||||
@ -742,7 +769,8 @@ class CallOptimization;
|
|||||||
|
|
||||||
class CallStubCompiler: public StubCompiler {
|
class CallStubCompiler: public StubCompiler {
|
||||||
public:
|
public:
|
||||||
CallStubCompiler(int argc,
|
CallStubCompiler(Isolate* isolate,
|
||||||
|
int argc,
|
||||||
Code::Kind kind,
|
Code::Kind kind,
|
||||||
Code::ExtraICState extra_ic_state,
|
Code::ExtraICState extra_ic_state,
|
||||||
InlineCacheHolderFlag cache_holder);
|
InlineCacheHolderFlag cache_holder);
|
||||||
@ -835,7 +863,7 @@ class CallStubCompiler: public StubCompiler {
|
|||||||
|
|
||||||
class ConstructStubCompiler: public StubCompiler {
|
class ConstructStubCompiler: public StubCompiler {
|
||||||
public:
|
public:
|
||||||
explicit ConstructStubCompiler() {}
|
explicit ConstructStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
|
||||||
|
|
||||||
MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
|
MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user