vendor/v8/src/ic.cc in mustang-0.0.1 vs vendor/v8/src/ic.cc in mustang-0.1.0
- old
+ new
@@ -63,12 +63,12 @@
State old_state,
Code* new_target,
const char* extra_info) {
if (FLAG_trace_ic) {
State new_state = StateFrom(new_target,
- Heap::undefined_value(),
- Heap::undefined_value());
+ HEAP->undefined_value(),
+ HEAP->undefined_value());
PrintF("[%s (%c->%c)%s", type,
TransitionMarkFromState(old_state),
TransitionMarkFromState(new_state),
extra_info);
name->Print();
@@ -76,15 +76,17 @@
}
}
#endif
-IC::IC(FrameDepth depth) {
+IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
+ ASSERT(isolate == Isolate::Current());
// To improve the performance of the (much used) IC code, we unfold
// a few levels of the stack frame iteration code. This yields a
// ~35% speedup when running DeltaBlue with the '--nouse-ic' flag.
- const Address entry = Top::c_entry_fp(Top::GetCurrentThread());
+ const Address entry =
+ Isolate::c_entry_fp(isolate->thread_local_top());
Address* pc_address =
reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
// If there's another JavaScript frame on the stack, we need to look
// one frame further down the stack to find the frame pointer and
@@ -134,13 +136,15 @@
return addr + delta;
}
#endif
-static bool HasNormalObjectsInPrototypeChain(LookupResult* lookup,
+static bool HasNormalObjectsInPrototypeChain(Isolate* isolate,
+ LookupResult* lookup,
Object* receiver) {
- Object* end = lookup->IsProperty() ? lookup->holder() : Heap::null_value();
+ Object* end = lookup->IsProperty()
+ ? lookup->holder() : isolate->heap()->null_value();
for (Object* current = receiver;
current != end;
current = current->GetPrototype()) {
if (current->IsJSObject() &&
!JSObject::cast(current)->HasFastProperties() &&
@@ -229,11 +233,11 @@
}
RelocInfo::Mode IC::ComputeMode() {
Address addr = address();
- Code* code = Code::cast(Heap::FindCodeObject(addr));
+ Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr));
for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
!it.done(); it.next()) {
RelocInfo* info = it.rinfo();
if (info->pc() == addr) return info->rmode();
}
@@ -243,22 +247,23 @@
Failure* IC::TypeError(const char* type,
Handle<Object> object,
Handle<Object> key) {
- HandleScope scope;
+ HandleScope scope(isolate());
Handle<Object> args[2] = { key, object };
- Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2));
- return Top::Throw(*error);
+ Handle<Object> error = isolate()->factory()->NewTypeError(
+ type, HandleVector(args, 2));
+ return isolate()->Throw(*error);
}
Failure* IC::ReferenceError(const char* type, Handle<String> name) {
- HandleScope scope;
- Handle<Object> error =
- Factory::NewReferenceError(type, HandleVector(&name, 1));
- return Top::Throw(*error);
+ HandleScope scope(isolate());
+ Handle<Object> error = isolate()->factory()->NewReferenceError(
+ type, HandleVector(&name, 1));
+ return isolate()->Throw(*error);
}
void IC::Clear(Address address) {
Code* target = GetTargetAtAddress(address);
@@ -266,13 +271,17 @@
// Don't clear debug break inline cache as it will remove the break point.
if (target->ic_state() == DEBUG_BREAK) return;
switch (target->kind()) {
case Code::LOAD_IC: return LoadIC::Clear(address, target);
- case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
+ case Code::KEYED_LOAD_IC:
+ case Code::KEYED_EXTERNAL_ARRAY_LOAD_IC:
+ return KeyedLoadIC::Clear(address, target);
case Code::STORE_IC: return StoreIC::Clear(address, target);
- case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
+ case Code::KEYED_STORE_IC:
+ case Code::KEYED_EXTERNAL_ARRAY_STORE_IC:
+ return KeyedStoreIC::Clear(address, target);
case Code::CALL_IC: return CallIC::Clear(address, target);
case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
case Code::BINARY_OP_IC:
case Code::TYPE_RECORDING_BINARY_OP_IC:
case Code::COMPARE_IC:
@@ -286,21 +295,22 @@
void CallICBase::Clear(Address address, Code* target) {
State state = target->ic_state();
if (state == UNINITIALIZED) return;
Code* code =
- StubCache::FindCallInitialize(target->arguments_count(),
- target->ic_in_loop(),
- target->kind());
+ Isolate::Current()->stub_cache()->FindCallInitialize(
+ target->arguments_count(),
+ target->ic_in_loop(),
+ target->kind());
SetTargetAtAddress(address, code);
}
void KeyedLoadIC::ClearInlinedVersion(Address address) {
// Insert null as the map to check for to make sure the map check fails
// sending control flow to the IC instead of the inlined version.
- PatchInlinedLoad(address, Heap::null_value());
+ PatchInlinedLoad(address, HEAP->null_value());
}
void KeyedLoadIC::Clear(Address address, Code* target) {
if (target->ic_state() == UNINITIALIZED) return;
@@ -314,14 +324,15 @@
void LoadIC::ClearInlinedVersion(Address address) {
// Reset the map check of the inlined inobject property load (if
// present) to guarantee failure by holding an invalid map (the null
// value). The offset can be patched to anything.
- PatchInlinedLoad(address, Heap::null_value(), 0);
+ Heap* heap = HEAP;
+ PatchInlinedLoad(address, heap->null_value(), 0);
PatchInlinedContextualLoad(address,
- Heap::null_value(),
- Heap::null_value(),
+ heap->null_value(),
+ heap->null_value(),
true);
}
void LoadIC::Clear(Address address, Code* target) {
@@ -333,42 +344,45 @@
void StoreIC::ClearInlinedVersion(Address address) {
// Reset the map check of the inlined inobject property store (if
// present) to guarantee failure by holding an invalid map (the null
// value). The offset can be patched to anything.
- PatchInlinedStore(address, Heap::null_value(), 0);
+ PatchInlinedStore(address, HEAP->null_value(), 0);
}
void StoreIC::Clear(Address address, Code* target) {
if (target->ic_state() == UNINITIALIZED) return;
ClearInlinedVersion(address);
SetTargetAtAddress(address,
- target->extra_ic_state() == kStoreICStrict
+ (target->extra_ic_state() == kStrictMode)
? initialize_stub_strict()
: initialize_stub());
}
void KeyedStoreIC::ClearInlinedVersion(Address address) {
// Insert null as the elements map to check for. This will make
// sure that the elements fast-case map check fails so that control
// flows to the IC instead of the inlined version.
- PatchInlinedStore(address, Heap::null_value());
+ PatchInlinedStore(address, HEAP->null_value());
}
void KeyedStoreIC::RestoreInlinedVersion(Address address) {
// Restore the fast-case elements map check so that the inlined
// version can be used again.
- PatchInlinedStore(address, Heap::fixed_array_map());
+ PatchInlinedStore(address, HEAP->fixed_array_map());
}
void KeyedStoreIC::Clear(Address address, Code* target) {
if (target->ic_state() == UNINITIALIZED) return;
- SetTargetAtAddress(address, initialize_stub());
+ SetTargetAtAddress(address,
+ (target->extra_ic_state() == kStrictMode)
+ ? initialize_stub_strict()
+ : initialize_stub());
}
static bool HasInterceptorGetter(JSObject* object) {
return !object->GetNamedInterceptor()->getter()->IsUndefined();
@@ -414,12 +428,12 @@
}
}
Object* CallICBase::TryCallAsFunction(Object* object) {
- HandleScope scope;
- Handle<Object> target(object);
+ HandleScope scope(isolate());
+ Handle<Object> target(object, isolate());
Handle<Object> delegate = Execution::GetFunctionDelegate(target);
if (delegate->IsJSFunction()) {
// Patch the receiver and use the delegate as the function to
// invoke. This is used for invoking objects as if they were
@@ -450,11 +464,11 @@
// Change the receiver to the result of calling ToObject on it.
const int argc = this->target()->arguments_count();
StackFrameLocator locator;
JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
int index = frame->ComputeExpressionsCount() - (argc + 1);
- frame->SetExpression(index, *Factory::ToObject(object));
+ frame->SetExpression(index, *isolate()->factory()->ToObject(object));
}
}
MaybeObject* CallICBase::LoadFunction(State state,
@@ -522,11 +536,11 @@
}
}
ASSERT(!result->IsTheHole());
- HandleScope scope;
+ HandleScope scope(isolate());
// Wrap result in a handle because ReceiverToObjectIfRequired may allocate
// new object and cause GC.
Handle<Object> result_handle(result);
// Make receiver an object if the callee requires it. Strict mode or builtin
// functions do not wrap the receiver, non-strict functions and objects
@@ -534,15 +548,16 @@
ReceiverToObjectIfRequired(result_handle, object);
if (result_handle->IsJSFunction()) {
#ifdef ENABLE_DEBUGGER_SUPPORT
// Handle stepping into a function if step into is active.
- if (Debug::StepInActive()) {
+ Debug* debug = isolate()->debug();
+ if (debug->StepInActive()) {
// Protect the result in a handle as the debugger can allocate and might
// cause GC.
- Handle<JSFunction> function(JSFunction::cast(*result_handle));
- Debug::HandleStepIn(function, object, fp(), false);
+ Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate());
+ debug->HandleStepIn(function, object, fp(), false);
return *function;
}
#endif
return *result_handle;
@@ -564,11 +579,11 @@
JSFunction* function = lookup->GetConstantFunction();
if (!function->shared()->HasBuiltinFunctionId()) return false;
// Fetch the arguments passed to the called function.
const int argc = target()->arguments_count();
- Address entry = Top::c_entry_fp(Top::GetCurrentThread());
+ Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
Arguments args(argc + 1,
&Memory::Object_at(fp +
StandardFrameConstants::kCallerSPOffset +
argc * kPointerSize));
@@ -614,32 +629,33 @@
InLoopFlag in_loop = target()->ic_in_loop();
MaybeObject* maybe_code = NULL;
switch (lookup->type()) {
case FIELD: {
int index = lookup->GetFieldIndex();
- maybe_code = StubCache::ComputeCallField(argc,
- in_loop,
- kind_,
- *name,
- *object,
- lookup->holder(),
- index);
+ maybe_code = isolate()->stub_cache()->ComputeCallField(argc,
+ in_loop,
+ kind_,
+ *name,
+ *object,
+ lookup->holder(),
+ index);
break;
}
case CONSTANT_FUNCTION: {
// Get the constant function and compute the code stub for this
// call; used for rewriting to monomorphic state and making sure
// that the code stub is in the stub cache.
JSFunction* function = lookup->GetConstantFunction();
- maybe_code = StubCache::ComputeCallConstant(argc,
- in_loop,
- kind_,
- extra_ic_state,
- *name,
- *object,
- lookup->holder(),
- function);
+ maybe_code =
+ isolate()->stub_cache()->ComputeCallConstant(argc,
+ in_loop,
+ kind_,
+ extra_ic_state,
+ *name,
+ *object,
+ lookup->holder(),
+ function);
break;
}
case NORMAL: {
if (!object->IsJSObject()) return NULL;
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
@@ -648,39 +664,40 @@
GlobalObject* global = GlobalObject::cast(lookup->holder());
JSGlobalPropertyCell* cell =
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
if (!cell->value()->IsJSFunction()) return NULL;
JSFunction* function = JSFunction::cast(cell->value());
- maybe_code = StubCache::ComputeCallGlobal(argc,
- in_loop,
- kind_,
- *name,
- *receiver,
- global,
- cell,
- function);
+ maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc,
+ in_loop,
+ kind_,
+ *name,
+ *receiver,
+ global,
+ cell,
+ function);
} else {
// There is only one shared stub for calling normalized
// properties. It does not traverse the prototype chain, so the
// property must be found in the receiver for the stub to be
// applicable.
if (lookup->holder() != *receiver) return NULL;
- maybe_code = StubCache::ComputeCallNormal(argc,
- in_loop,
- kind_,
- *name,
- *receiver);
+ maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc,
+ in_loop,
+ kind_,
+ *name,
+ *receiver);
}
break;
}
case INTERCEPTOR: {
ASSERT(HasInterceptorGetter(lookup->holder()));
- maybe_code = StubCache::ComputeCallInterceptor(argc,
- kind_,
- *name,
- *object,
- lookup->holder());
+ maybe_code = isolate()->stub_cache()->ComputeCallInterceptor(
+ argc,
+ kind_,
+ *name,
+ *object,
+ lookup->holder());
break;
}
default:
maybe_code = NULL;
break;
@@ -696,11 +713,12 @@
Handle<String> name) {
// Bail out if we didn't find a result.
if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
if (lookup->holder() != *object &&
- HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) {
+ HasNormalObjectsInPrototypeChain(
+ isolate(), lookup, object->GetPrototype())) {
// Suppress optimization for prototype chains with slow properties objects
// in the middle.
return;
}
@@ -711,11 +729,13 @@
bool had_proto_failure = false;
if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay
// setting the monomorphic state.
- maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
+ maybe_code = isolate()->stub_cache()->ComputeCallPreMonomorphic(argc,
+ in_loop,
+ kind_);
} else if (state == MONOMORPHIC) {
if (kind_ == Code::CALL_IC &&
TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
maybe_code = ComputeMonomorphicStub(lookup,
state,
@@ -731,11 +751,13 @@
state,
extra_ic_state,
object,
name);
} else {
- maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
+ maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(argc,
+ in_loop,
+ kind_);
}
} else {
maybe_code = ComputeMonomorphicStub(lookup,
state,
extra_ic_state,
@@ -759,11 +781,11 @@
// GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
Map* map = JSObject::cast(object->IsJSObject() ? *object :
object->GetPrototype())->map();
// Update the stub cache.
- StubCache::Set(*name, map, Code::cast(code));
+ isolate()->stub_cache()->Set(*name, map, Code::cast(code));
}
USE(had_proto_failure);
#ifdef DEBUG
if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
@@ -788,11 +810,11 @@
}
if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
int argc = target()->arguments_count();
InLoopFlag in_loop = target()->ic_in_loop();
- MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic(
+ MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(
argc, in_loop, Code::KEYED_CALL_IC);
Object* code;
if (maybe_code->ToObject(&code)) {
set_target(Code::cast(code));
#ifdef DEBUG
@@ -800,12 +822,13 @@
"KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : "");
#endif
}
}
- HandleScope scope;
+ HandleScope scope(isolate());
Handle<Object> result = GetProperty(object, key);
+ RETURN_IF_EMPTY_HANDLE(isolate(), result);
// Make receiver an object if the callee requires it. Strict mode or builtin
// functions do not wrap the receiver, non-strict functions and objects
// called as functions do.
ReceiverToObjectIfRequired(result, object);
@@ -842,60 +865,68 @@
// Use specialized code for getting the length of strings and
// string wrapper objects. The length property of string wrapper
// objects is read-only and therefore always returns the length of
// the underlying string value. See ECMA-262 15.5.5.1.
if ((object->IsString() || object->IsStringWrapper()) &&
- name->Equals(Heap::length_symbol())) {
- HandleScope scope;
+ name->Equals(isolate()->heap()->length_symbol())) {
+ HandleScope scope(isolate());
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
#endif
if (state == PREMONOMORPHIC) {
if (object->IsString()) {
Map* map = HeapObject::cast(*object)->map();
const int offset = String::kLengthOffset;
PatchInlinedLoad(address(), map, offset);
- set_target(Builtins::builtin(Builtins::LoadIC_StringLength));
+ set_target(isolate()->builtins()->builtin(
+ Builtins::kLoadIC_StringLength));
} else {
- set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength));
+ set_target(isolate()->builtins()->builtin(
+ Builtins::kLoadIC_StringWrapperLength));
}
} else if (state == MONOMORPHIC && object->IsStringWrapper()) {
- set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength));
+ set_target(isolate()->builtins()->builtin(
+ Builtins::kLoadIC_StringWrapperLength));
} else {
set_target(non_monomorphic_stub);
}
// Get the string if we have a string wrapper object.
if (object->IsJSValue()) {
- object = Handle<Object>(Handle<JSValue>::cast(object)->value());
+ object = Handle<Object>(Handle<JSValue>::cast(object)->value(),
+ isolate());
}
return Smi::FromInt(String::cast(*object)->length());
}
// Use specialized code for getting the length of arrays.
- if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
+ if (object->IsJSArray() &&
+ name->Equals(isolate()->heap()->length_symbol())) {
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
#endif
if (state == PREMONOMORPHIC) {
Map* map = HeapObject::cast(*object)->map();
const int offset = JSArray::kLengthOffset;
PatchInlinedLoad(address(), map, offset);
- set_target(Builtins::builtin(Builtins::LoadIC_ArrayLength));
+ set_target(isolate()->builtins()->builtin(
+ Builtins::kLoadIC_ArrayLength));
} else {
set_target(non_monomorphic_stub);
}
return JSArray::cast(*object)->length();
}
// Use specialized code for getting prototype of functions.
- if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
+ if (object->IsJSFunction() &&
+ name->Equals(isolate()->heap()->prototype_symbol()) &&
JSFunction::cast(*object)->should_have_prototype()) {
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
#endif
if (state == PREMONOMORPHIC) {
- set_target(Builtins::builtin(Builtins::LoadIC_FunctionPrototype));
+ set_target(isolate()->builtins()->builtin(
+ Builtins::kLoadIC_FunctionPrototype));
} else {
set_target(non_monomorphic_stub);
}
return Accessors::FunctionGetPrototype(*object, 0);
}
@@ -913,11 +944,11 @@
// If we did not find a property, check if we need to throw an exception.
if (!lookup.IsProperty()) {
if (FLAG_strict || IsContextual(object)) {
return ReferenceError("not_defined", name);
}
- LOG(SuspectReadEvent(*name, *object));
+ LOG(isolate(), SuspectReadEvent(*name, *object));
}
bool can_be_inlined_precheck =
FLAG_use_ic &&
lookup.IsProperty() &&
@@ -964,11 +995,11 @@
map,
cell,
lookup.IsDontDelete())) {
set_target(megamorphic_stub());
TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name);
- ASSERT(cell->value() != Heap::the_hole_value());
+ ASSERT(cell->value() != isolate()->heap()->the_hole_value());
return cell->value();
}
} else {
if (FLAG_use_ic && state == PREMONOMORPHIC) {
TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inlinable)]\n", name);
@@ -1011,11 +1042,11 @@
// Loading properties from values is not common, so don't try to
// deal with non-JS objects here.
if (!object->IsJSObject()) return;
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
- if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
+ if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
// Compute the code stub for this load.
MaybeObject* maybe_code = NULL;
Object* code;
if (state == UNINITIALIZED) {
@@ -1023,59 +1054,62 @@
// Set the target to the pre monomorphic stub to delay
// setting the monomorphic state.
maybe_code = pre_monomorphic_stub();
} else if (!lookup->IsProperty()) {
// Nonexistent property. The result is undefined.
- maybe_code = StubCache::ComputeLoadNonexistent(*name, *receiver);
+ maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name,
+ *receiver);
} else {
// Compute monomorphic stub.
switch (lookup->type()) {
case FIELD: {
- maybe_code = StubCache::ComputeLoadField(*name, *receiver,
- lookup->holder(),
- lookup->GetFieldIndex());
+ maybe_code = isolate()->stub_cache()->ComputeLoadField(
+ *name,
+ *receiver,
+ lookup->holder(),
+ lookup->GetFieldIndex());
break;
}
case CONSTANT_FUNCTION: {
Object* constant = lookup->GetConstantFunction();
- maybe_code = StubCache::ComputeLoadConstant(*name, *receiver,
- lookup->holder(), constant);
+ maybe_code = isolate()->stub_cache()->ComputeLoadConstant(
+ *name, *receiver, lookup->holder(), constant);
break;
}
case NORMAL: {
if (lookup->holder()->IsGlobalObject()) {
GlobalObject* global = GlobalObject::cast(lookup->holder());
JSGlobalPropertyCell* cell =
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
- maybe_code = StubCache::ComputeLoadGlobal(*name,
+ maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name,
*receiver,
global,
cell,
lookup->IsDontDelete());
} else {
// There is only one shared stub for loading normalized
// properties. It does not traverse the prototype chain, so the
// property must be found in the receiver for the stub to be
// applicable.
if (lookup->holder() != *receiver) return;
- maybe_code = StubCache::ComputeLoadNormal();
+ maybe_code = isolate()->stub_cache()->ComputeLoadNormal();
}
break;
}
case CALLBACKS: {
if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
AccessorInfo* callback =
AccessorInfo::cast(lookup->GetCallbackObject());
if (v8::ToCData<Address>(callback->getter()) == 0) return;
- maybe_code = StubCache::ComputeLoadCallback(*name, *receiver,
- lookup->holder(), callback);
+ maybe_code = isolate()->stub_cache()->ComputeLoadCallback(
+ *name, *receiver, lookup->holder(), callback);
break;
}
case INTERCEPTOR: {
ASSERT(HasInterceptorGetter(lookup->holder()));
- maybe_code = StubCache::ComputeLoadInterceptor(*name, *receiver,
- lookup->holder());
+ maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor(
+ *name, *receiver, lookup->holder());
break;
}
default:
return;
}
@@ -1095,11 +1129,11 @@
// Cache code holding map should be consistent with
// GenerateMonomorphicCacheProbe.
Map* map = JSObject::cast(object->IsJSObject() ? *object :
object->GetPrototype())->map();
- StubCache::Set(*name, map, Code::cast(code));
+ isolate()->stub_cache()->Set(*name, map, Code::cast(code));
}
#ifdef DEBUG
TraceIC("LoadIC", name, state, target());
#endif
@@ -1107,10 +1141,20 @@
MaybeObject* KeyedLoadIC::Load(State state,
Handle<Object> object,
Handle<Object> key) {
+ // Check for values that can be converted into a symbol.
+ // TODO(1295): Remove this code.
+ HandleScope scope(isolate());
+ if (key->IsHeapNumber() &&
+ isnan(HeapNumber::cast(*key)->value())) {
+ key = isolate()->factory()->nan_symbol();
+ } else if (key->IsUndefined()) {
+ key = isolate()->factory()->undefined_symbol();
+ }
+
if (key->IsSymbol()) {
Handle<String> name = Handle<String>::cast(key);
// If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case.
@@ -1120,46 +1164,52 @@
if (FLAG_use_ic) {
// TODO(1073): don't ignore the current stub state.
// Use specialized code for getting the length of strings.
- if (object->IsString() && name->Equals(Heap::length_symbol())) {
+ if (object->IsString() &&
+ name->Equals(isolate()->heap()->length_symbol())) {
Handle<String> string = Handle<String>::cast(object);
Object* code = NULL;
{ MaybeObject* maybe_code =
- StubCache::ComputeKeyedLoadStringLength(*name, *string);
+ isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name,
+ *string);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code));
#ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target());
#endif // DEBUG
return Smi::FromInt(string->length());
}
// Use specialized code for getting the length of arrays.
- if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
+ if (object->IsJSArray() &&
+ name->Equals(isolate()->heap()->length_symbol())) {
Handle<JSArray> array = Handle<JSArray>::cast(object);
Object* code;
{ MaybeObject* maybe_code =
- StubCache::ComputeKeyedLoadArrayLength(*name, *array);
+ isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name,
+ *array);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code));
#ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target());
#endif // DEBUG
return JSArray::cast(*object)->length();
}
// Use specialized code for getting prototype of functions.
- if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
+ if (object->IsJSFunction() &&
+ name->Equals(isolate()->heap()->prototype_symbol()) &&
JSFunction::cast(*object)->should_have_prototype()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(object);
Object* code;
{ MaybeObject* maybe_code =
- StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);
+ isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
+ *name, *function);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code));
#ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target());
@@ -1170,14 +1220,14 @@
// Check if the name is trivially convertible to an index and get
// the element or char if so.
uint32_t index = 0;
if (name->AsArrayIndex(&index)) {
- HandleScope scope;
+ HandleScope scope(isolate());
// Rewrite to the generic keyed load stub.
if (FLAG_use_ic) set_target(generic_stub());
- return Runtime::GetElementOrCharAt(object, index);
+ return Runtime::GetElementOrCharAt(isolate(), object, index);
}
// Named lookup.
LookupResult lookup;
LookupForRead(*object, *name, &lookup);
@@ -1223,25 +1273,20 @@
stub = string_stub();
} else if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
if (receiver->HasExternalArrayElements()) {
MaybeObject* probe =
- StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver,
- false);
+ isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
+ *receiver, false, kNonStrictMode);
stub = probe->IsFailure() ?
NULL : Code::cast(probe->ToObjectUnchecked());
} else if (receiver->HasIndexedInterceptor()) {
stub = indexed_interceptor_stub();
- } else if (receiver->HasPixelElements()) {
- MaybeObject* probe =
- StubCache::ComputeKeyedLoadPixelArray(*receiver);
- stub = probe->IsFailure() ?
- NULL : Code::cast(probe->ToObjectUnchecked());
} else if (key->IsSmi() &&
receiver->map()->has_fast_elements()) {
MaybeObject* probe =
- StubCache::ComputeKeyedLoadSpecialized(*receiver);
+ isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver);
stub = probe->IsFailure() ?
NULL : Code::cast(probe->ToObjectUnchecked());
}
}
}
@@ -1263,11 +1308,11 @@
PatchInlinedLoad(address(), map);
}
}
// Get the property.
- return Runtime::GetObjectProperty(object, key);
+ return Runtime::GetObjectProperty(isolate(), object, key);
}
void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
Handle<Object> object, Handle<String> name) {
@@ -1275,11 +1320,11 @@
if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
if (!object->IsJSObject()) return;
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
- if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
+ if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
// Compute the code stub for this load.
MaybeObject* maybe_code = NULL;
Object* code;
@@ -1290,38 +1335,33 @@
maybe_code = pre_monomorphic_stub();
} else {
// Compute a monomorphic stub.
switch (lookup->type()) {
case FIELD: {
- maybe_code = StubCache::ComputeKeyedLoadField(*name, *receiver,
- lookup->holder(),
- lookup->GetFieldIndex());
+ maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField(
+ *name, *receiver, lookup->holder(), lookup->GetFieldIndex());
break;
}
case CONSTANT_FUNCTION: {
Object* constant = lookup->GetConstantFunction();
- maybe_code = StubCache::ComputeKeyedLoadConstant(*name,
- *receiver,
- lookup->holder(),
- constant);
+ maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
+ *name, *receiver, lookup->holder(), constant);
break;
}
case CALLBACKS: {
if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
AccessorInfo* callback =
AccessorInfo::cast(lookup->GetCallbackObject());
if (v8::ToCData<Address>(callback->getter()) == 0) return;
- maybe_code = StubCache::ComputeKeyedLoadCallback(*name,
- *receiver,
- lookup->holder(),
- callback);
+ maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
+ *name, *receiver, lookup->holder(), callback);
break;
}
case INTERCEPTOR: {
ASSERT(HasInterceptorGetter(lookup->holder()));
- maybe_code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver,
- lookup->holder());
+ maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
+ *name, *receiver, lookup->holder());
break;
}
default: {
// Always rewrite to the generic case so that we do not
// repeatedly try to rewrite.
@@ -1380,45 +1420,53 @@
return true;
}
MaybeObject* StoreIC::Store(State state,
- Code::ExtraICState extra_ic_state,
+ StrictModeFlag strict_mode,
Handle<Object> object,
Handle<String> name,
Handle<Object> value) {
// If the object is undefined or null it's illegal to try to set any
// properties on it; throw a TypeError in that case.
if (object->IsUndefined() || object->IsNull()) {
return TypeError("non_object_property_store", object, name);
}
- // Ignore stores where the receiver is not a JSObject.
- if (!object->IsJSObject()) return *value;
+ if (!object->IsJSObject()) {
+ // The length property of string values is read-only. Throw in strict mode.
+ if (strict_mode == kStrictMode && object->IsString() &&
+ name->Equals(isolate()->heap()->length_symbol())) {
+ return TypeError("strict_read_only_property", object, name);
+ }
+ // Ignore stores where the receiver is not a JSObject.
+ return *value;
+ }
+
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
// Check if the given name is an array index.
uint32_t index;
if (name->AsArrayIndex(&index)) {
- HandleScope scope;
- Handle<Object> result = SetElement(receiver, index, value);
+ HandleScope scope(isolate());
+ Handle<Object> result = SetElement(receiver, index, value, strict_mode);
if (result.is_null()) return Failure::Exception();
return *value;
}
// Use specialized code for setting the length of arrays.
if (receiver->IsJSArray()
- && name->Equals(Heap::length_symbol())
+ && name->Equals(isolate()->heap()->length_symbol())
&& receiver->AllowsSetElementsLength()) {
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
#endif
- Builtins::Name target = (extra_ic_state == kStoreICStrict)
- ? Builtins::StoreIC_ArrayLength_Strict
- : Builtins::StoreIC_ArrayLength;
- set_target(Builtins::builtin(target));
- return receiver->SetProperty(*name, *value, NONE);
+ Builtins::Name target = (strict_mode == kStrictMode)
+ ? Builtins::kStoreIC_ArrayLength_Strict
+ : Builtins::kStoreIC_ArrayLength;
+ set_target(isolate()->builtins()->builtin(target));
+ return receiver->SetProperty(*name, *value, NONE, strict_mode);
}
// Lookup the property locally in the receiver.
if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
LookupResult lookup;
@@ -1438,17 +1486,19 @@
int index = lookup.GetFieldIndex() - map->inobject_properties();
if (index < 0) {
// Index is an offset from the end of the object.
int offset = map->instance_size() + (index * kPointerSize);
if (PatchInlinedStore(address(), map, offset)) {
- set_target(megamorphic_stub());
+ set_target((strict_mode == kStrictMode)
+ ? megamorphic_stub_strict()
+ : megamorphic_stub());
#ifdef DEBUG
if (FLAG_trace_ic) {
PrintF("[StoreIC : inline patch %s]\n", *name->ToCString());
}
#endif
- return receiver->SetProperty(*name, *value, NONE);
+ return receiver->SetProperty(*name, *value, NONE, strict_mode);
#ifdef DEBUG
} else {
if (FLAG_trace_ic) {
PrintF("[StoreIC : no inline patch %s (patching failed)]\n",
@@ -1471,23 +1521,28 @@
}
}
// If no inlined store ic was patched, generate a stub for this
// store.
- UpdateCaches(&lookup, state, extra_ic_state, receiver, name, value);
+ UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
} else {
- // Strict mode doesn't allow setting non-existent global property.
- if (extra_ic_state == kStoreICStrict && IsContextual(object)) {
- return ReferenceError("not_defined", name);
+ // Strict mode doesn't allow setting non-existent global property
+ // or an assignment to a read only property.
+ if (strict_mode == kStrictMode) {
+ if (lookup.IsFound() && lookup.IsReadOnly()) {
+ return TypeError("strict_read_only_property", object, name);
+ } else if (IsContextual(object)) {
+ return ReferenceError("not_defined", name);
+ }
}
}
}
if (receiver->IsJSGlobalProxy()) {
// Generate a generic stub that goes to the runtime when we see a global
// proxy as receiver.
- Code* stub = (extra_ic_state == kStoreICStrict)
+ Code* stub = (strict_mode == kStrictMode)
? global_proxy_stub_strict()
: global_proxy_stub();
if (target() != stub) {
set_target(stub);
#ifdef DEBUG
@@ -1495,17 +1550,17 @@
#endif
}
}
// Set the property.
- return receiver->SetProperty(*name, *value, NONE);
+ return receiver->SetProperty(*name, *value, NONE, strict_mode);
}
void StoreIC::UpdateCaches(LookupResult* lookup,
State state,
- Code::ExtraICState extra_ic_state,
+ StrictModeFlag strict_mode,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value) {
// Skip JSGlobalProxy.
ASSERT(!receiver->IsJSGlobalProxy());
@@ -1522,52 +1577,52 @@
// stub cache.
MaybeObject* maybe_code = NULL;
Object* code = NULL;
switch (type) {
case FIELD: {
- maybe_code = StubCache::ComputeStoreField(
- *name, *receiver, lookup->GetFieldIndex(), NULL, extra_ic_state);
+ maybe_code = isolate()->stub_cache()->ComputeStoreField(
+ *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
break;
}
case MAP_TRANSITION: {
if (lookup->GetAttributes() != NONE) return;
- HandleScope scope;
+ HandleScope scope(isolate());
ASSERT(type == MAP_TRANSITION);
Handle<Map> transition(lookup->GetTransitionMap());
int index = transition->PropertyIndexFor(*name);
- maybe_code = StubCache::ComputeStoreField(
- *name, *receiver, index, *transition, extra_ic_state);
+ maybe_code = isolate()->stub_cache()->ComputeStoreField(
+ *name, *receiver, index, *transition, strict_mode);
break;
}
case NORMAL: {
if (receiver->IsGlobalObject()) {
// The stub generated for the global object picks the value directly
// from the property cell. So the property must be directly on the
// global object.
Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
JSGlobalPropertyCell* cell =
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
- maybe_code = StubCache::ComputeStoreGlobal(
- *name, *global, cell, extra_ic_state);
+ maybe_code = isolate()->stub_cache()->ComputeStoreGlobal(
+ *name, *global, cell, strict_mode);
} else {
if (lookup->holder() != *receiver) return;
- maybe_code = StubCache::ComputeStoreNormal(extra_ic_state);
+ maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
}
break;
}
case CALLBACKS: {
if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
if (v8::ToCData<Address>(callback->setter()) == 0) return;
- maybe_code = StubCache::ComputeStoreCallback(
- *name, *receiver, callback, extra_ic_state);
+ maybe_code = isolate()->stub_cache()->ComputeStoreCallback(
+ *name, *receiver, callback, strict_mode);
break;
}
case INTERCEPTOR: {
ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
- maybe_code = StubCache::ComputeStoreInterceptor(
- *name, *receiver, extra_ic_state);
+ maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor(
+ *name, *receiver, strict_mode);
break;
}
default:
return;
}
@@ -1580,26 +1635,29 @@
if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
set_target(Code::cast(code));
} else if (state == MONOMORPHIC) {
// Only move to megamorphic if the target changes.
if (target() != Code::cast(code)) {
- set_target(extra_ic_state == kStoreICStrict
+ set_target((strict_mode == kStrictMode)
? megamorphic_stub_strict()
: megamorphic_stub());
}
} else if (state == MEGAMORPHIC) {
// Update the stub cache.
- StubCache::Set(*name, receiver->map(), Code::cast(code));
+ isolate()->stub_cache()->Set(*name,
+ receiver->map(),
+ Code::cast(code));
}
#ifdef DEBUG
TraceIC("StoreIC", name, state, target());
#endif
}
MaybeObject* KeyedStoreIC::Store(State state,
+ StrictModeFlag strict_mode,
Handle<Object> object,
Handle<Object> key,
Handle<Object> value) {
if (key->IsSymbol()) {
Handle<String> name = Handle<String>::cast(key);
@@ -1615,67 +1673,67 @@
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
// Check if the given name is an array index.
uint32_t index;
if (name->AsArrayIndex(&index)) {
- HandleScope scope;
- Handle<Object> result = SetElement(receiver, index, value);
+ HandleScope scope(isolate());
+ Handle<Object> result = SetElement(receiver, index, value, strict_mode);
if (result.is_null()) return Failure::Exception();
return *value;
}
// Lookup the property locally in the receiver.
LookupResult lookup;
receiver->LocalLookup(*name, &lookup);
// Update inline cache and stub cache.
if (FLAG_use_ic) {
- UpdateCaches(&lookup, state, receiver, name, value);
+ UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
}
// Set the property.
- return receiver->SetProperty(*name, *value, NONE);
+ return receiver->SetProperty(*name, *value, NONE, strict_mode);
}
// Do not use ICs for objects that require access checks (including
// the global object).
bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
ASSERT(!(use_ic && object->IsJSGlobalProxy()));
if (use_ic) {
- Code* stub = generic_stub();
+ Code* stub =
+ (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub();
if (state == UNINITIALIZED) {
if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
if (receiver->HasExternalArrayElements()) {
MaybeObject* probe =
- StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, true);
+ isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
+ *receiver, true, strict_mode);
stub = probe->IsFailure() ?
NULL : Code::cast(probe->ToObjectUnchecked());
- } else if (receiver->HasPixelElements()) {
- MaybeObject* probe =
- StubCache::ComputeKeyedStorePixelArray(*receiver);
- stub = probe->IsFailure() ?
- NULL : Code::cast(probe->ToObjectUnchecked());
} else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
MaybeObject* probe =
- StubCache::ComputeKeyedStoreSpecialized(*receiver);
+ isolate()->stub_cache()->ComputeKeyedStoreSpecialized(
+ *receiver, strict_mode);
stub = probe->IsFailure() ?
NULL : Code::cast(probe->ToObjectUnchecked());
}
}
}
if (stub != NULL) set_target(stub);
}
// Set the property.
- return Runtime::SetObjectProperty(object, key, value, NONE);
+ return Runtime::SetObjectProperty(
+ isolate(), object , key, value, NONE, strict_mode);
}
void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
State state,
+ StrictModeFlag strict_mode,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value) {
// Skip JSGlobalProxy.
if (receiver->IsJSGlobalProxy()) return;
@@ -1698,30 +1756,32 @@
MaybeObject* maybe_code = NULL;
Object* code = NULL;
switch (type) {
case FIELD: {
- maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
- lookup->GetFieldIndex());
+ maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
+ *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
break;
}
case MAP_TRANSITION: {
if (lookup->GetAttributes() == NONE) {
- HandleScope scope;
+ HandleScope scope(isolate());
ASSERT(type == MAP_TRANSITION);
Handle<Map> transition(lookup->GetTransitionMap());
int index = transition->PropertyIndexFor(*name);
- maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
- index, *transition);
+ maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
+ *name, *receiver, index, *transition, strict_mode);
break;
}
// fall through.
}
default: {
// Always rewrite to the generic case so that we do not
// repeatedly try to rewrite.
- maybe_code = generic_stub();
+ maybe_code = (strict_mode == kStrictMode)
+ ? generic_stub_strict()
+ : generic_stub();
break;
}
}
// If we're unable to compute the stub (not enough memory left), we
@@ -1732,11 +1792,13 @@
// sure to always rewrite from monomorphic to megamorphic.
ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
set_target(Code::cast(code));
} else if (state == MONOMORPHIC) {
- set_target(megamorphic_stub());
+ set_target((strict_mode == kStrictMode)
+ ? megamorphic_stub_strict()
+ : megamorphic_stub());
}
#ifdef DEBUG
TraceIC("KeyedStoreIC", name, state, target());
#endif
@@ -1745,29 +1807,30 @@
// ----------------------------------------------------------------------------
// Static IC stub generators.
//
-static JSFunction* CompileFunction(JSFunction* function,
+static JSFunction* CompileFunction(Isolate* isolate,
+ JSFunction* function,
InLoopFlag in_loop) {
// Compile now with optimization.
- HandleScope scope;
- Handle<JSFunction> function_handle(function);
+ HandleScope scope(isolate);
+ Handle<JSFunction> function_handle(function, isolate);
if (in_loop == IN_LOOP) {
CompileLazyInLoop(function_handle, CLEAR_EXCEPTION);
} else {
CompileLazy(function_handle, CLEAR_EXCEPTION);
}
return *function_handle;
}
// Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
- CallIC ic;
+ CallIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
MaybeObject* maybe_result = ic.LoadFunction(state,
extra_ic_state,
args.at<Object>(0),
@@ -1783,66 +1846,73 @@
// do this in the case where we know that the inline cache is inside a loop,
// because then we know that we want to optimize the function.
if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
return result;
}
- return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop());
+ return CompileFunction(isolate,
+ JSFunction::cast(result),
+ ic.target()->ic_in_loop());
}
// Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
- KeyedCallIC ic;
+ KeyedCallIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Object* result;
{ MaybeObject* maybe_result =
ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
return result;
}
- return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop());
+ return CompileFunction(isolate,
+ JSFunction::cast(result),
+ ic.target()->ic_in_loop());
}
// Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* LoadIC_Miss(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
- LoadIC ic;
+ LoadIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
return ic.Load(state, args.at<Object>(0), args.at<String>(1));
}
// Used from ic-<arch>.cc
-MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
- KeyedLoadIC ic;
+ KeyedLoadIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
}
// Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
NoHandleAllocation na;
ASSERT(args.length() == 3);
- StoreIC ic;
+ StoreIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
- return ic.Store(state, extra_ic_state, args.at<Object>(0),
- args.at<String>(1), args.at<Object>(2));
+ return ic.Store(state,
+ static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+ args.at<Object>(0),
+ args.at<String>(1),
+ args.at<Object>(2));
}
-MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
NoHandleAllocation nha;
ASSERT(args.length() == 2);
JSObject* receiver = JSObject::cast(args[0]);
Object* len = args[1];
@@ -1859,11 +1929,11 @@
// Extend storage is called in a store inline cache when
// it is necessary to extend the properties array of a
// JSObject.
-MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
NoHandleAllocation na;
ASSERT(args.length() == 3);
// Convert the parameters
JSObject* object = JSObject::cast(args[0]);
@@ -1893,16 +1963,20 @@
return value;
}
// Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
NoHandleAllocation na;
ASSERT(args.length() == 3);
- KeyedStoreIC ic;
+ KeyedStoreIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
- return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
+ Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
+ return ic.Store(state,
+ static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+ args.at<Object>(0),
+ args.at<Object>(1),
args.at<Object>(2));
}
void BinaryOpIC::patch(Code* code) {
@@ -1962,35 +2036,36 @@
// defined in code-stubs-<arch>.cc
Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info);
-MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
ASSERT(args.length() == 5);
- HandleScope scope;
+ HandleScope scope(isolate);
Handle<Object> left = args.at<Object>(0);
Handle<Object> right = args.at<Object>(1);
int key = Smi::cast(args[2])->value();
Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
BinaryOpIC::TypeInfo previous_type =
static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());
BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(*left, *right);
Handle<Code> code = GetBinaryOpStub(key, type);
if (!code.is_null()) {
- BinaryOpIC ic;
+ BinaryOpIC ic(isolate);
ic.patch(*code);
if (FLAG_trace_ic) {
PrintF("[BinaryOpIC (%s->%s)#%s]\n",
BinaryOpIC::GetName(previous_type),
BinaryOpIC::GetName(type),
Token::Name(op));
}
}
- Handle<JSBuiltinsObject> builtins = Top::builtins();
+ Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
+ isolate->thread_local_top()->context_->builtins(), isolate);
Object* builtin = NULL; // Initialization calms down the compiler.
switch (op) {
case Token::ADD:
builtin = builtins->javascript_builtin(Builtins::ADD);
break;
@@ -2026,11 +2101,12 @@
break;
default:
UNREACHABLE();
}
- Handle<JSFunction> builtin_function(JSFunction::cast(builtin));
+ Handle<JSFunction> builtin_function(JSFunction::cast(builtin),
+ isolate);
bool caught_exception;
Object** builtin_args[] = { right.location() };
Handle<Object> result = Execution::Call(builtin_function,
left,
@@ -2053,10 +2129,11 @@
switch (type_info) {
case UNINITIALIZED: return "Uninitialized";
case SMI: return "SMI";
case INT32: return "Int32s";
case HEAP_NUMBER: return "HeapNumbers";
+ case ODDBALL: return "Oddball";
case STRING: return "Strings";
case GENERIC: return "Generic";
default: return "Invalid";
}
}
@@ -2067,10 +2144,11 @@
case UNINITIALIZED:
return ::v8::internal::UNINITIALIZED;
case SMI:
case INT32:
case HEAP_NUMBER:
+ case ODDBALL:
case STRING:
return MONOMORPHIC;
case GENERIC:
return MEGAMORPHIC;
}
@@ -2114,10 +2192,14 @@
// Patching for fast string ADD makes sense even if only one of the
// arguments is a string.
return STRING;
}
+ // Check for oddball objects.
+ if (left->IsUndefined() && right->IsNumber()) return ODDBALL;
+ if (left->IsNumber() && right->IsUndefined()) return ODDBALL;
+
return GENERIC;
}
// defined in code-stubs-<arch>.cc
@@ -2125,14 +2207,14 @@
Handle<Code> GetTypeRecordingBinaryOpStub(int key,
TRBinaryOpIC::TypeInfo type_info,
TRBinaryOpIC::TypeInfo result_type);
-MaybeObject* TypeRecordingBinaryOp_Patch(Arguments args) {
+RUNTIME_FUNCTION(MaybeObject*, TypeRecordingBinaryOp_Patch) {
ASSERT(args.length() == 5);
- HandleScope scope;
+ HandleScope scope(isolate);
Handle<Object> left = args.at<Object>(0);
Handle<Object> right = args.at<Object>(1);
int key = Smi::cast(args[2])->value();
Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
TRBinaryOpIC::TypeInfo previous_type =
@@ -2170,20 +2252,21 @@
TRBinaryOpIC::GetName(previous_type),
TRBinaryOpIC::GetName(type),
TRBinaryOpIC::GetName(result_type),
Token::Name(op));
}
- TRBinaryOpIC ic;
+ TRBinaryOpIC ic(isolate);
ic.patch(*code);
// Activate inlined smi code.
if (previous_type == TRBinaryOpIC::UNINITIALIZED) {
PatchInlinedSmiCode(ic.address());
}
}
- Handle<JSBuiltinsObject> builtins = Top::builtins();
+ Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
+ isolate->thread_local_top()->context_->builtins(), isolate);
Object* builtin = NULL; // Initialization calms down the compiler.
switch (op) {
case Token::ADD:
builtin = builtins->javascript_builtin(Builtins::ADD);
break;
@@ -2219,11 +2302,11 @@
break;
default:
UNREACHABLE();
}
- Handle<JSFunction> builtin_function(JSFunction::cast(builtin));
+ Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
bool caught_exception;
Object** builtin_args[] = { right.location() };
Handle<Object> result = Execution::Call(builtin_function,
left,
@@ -2279,19 +2362,19 @@
return GENERIC;
}
// Used from ic_<arch>.cc.
-Code* CompareIC_Miss(Arguments args) {
+RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
NoHandleAllocation na;
ASSERT(args.length() == 3);
- CompareIC ic(static_cast<Token::Value>(Smi::cast(args[2])->value()));
+ CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value()));
ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
return ic.target();
}
-static Address IC_utilities[] = {
+static const Address IC_utilities[] = {
#define ADDR(name) FUNCTION_ADDR(name),
IC_UTIL_LIST(ADDR)
NULL
#undef ADDR
};