Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Unified Diff: src/ic.cc

Issue 6614010: [Isolates] Merge 6700:7030 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ic.cc
===================================================================
--- src/ic.cc (revision 7031)
+++ src/ic.cc (working copy)
@@ -349,7 +349,10 @@
void StoreIC::Clear(Address address, Code* target) {
if (target->ic_state() == UNINITIALIZED) return;
ClearInlinedVersion(address);
- SetTargetAtAddress(address, initialize_stub());
+ SetTargetAtAddress(address,
+ (target->extra_ic_state() == kStrictMode)
+ ? initialize_stub_strict()
+ : initialize_stub());
}
@@ -370,7 +373,10 @@
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());
}
@@ -439,16 +445,25 @@
}
-void CallICBase::ReceiverToObject(Handle<Object> object) {
- HandleScope scope(isolate());
- Handle<Object> receiver = object;
+void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
+ Handle<Object> object) {
+ if (callee->IsJSFunction()) {
+ Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
+ if (function->shared()->strict_mode() || function->IsBuiltin()) {
+ // Do not wrap receiver for strict mode functions or for builtins.
+ return;
+ }
+ }
- // 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, *isolate()->factory()->ToObject(object));
+ // And only wrap string, number or boolean.
+ if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
+ // 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, *isolate()->factory()->ToObject(object));
+ }
}
@@ -462,10 +477,6 @@
return TypeError("non_object_property_call", object, name);
}
- if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
- ReceiverToObject(object);
- }
-
// Check if the name is trivially convertible to an index and get
// the element if so.
uint32_t index;
@@ -509,6 +520,7 @@
object->GetProperty(*object, &lookup, *name, &attr);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
+
if (lookup.type() == INTERCEPTOR) {
// If the object does not have the requested property, check which
// exception we need to throw.
@@ -520,32 +532,38 @@
}
}
- ASSERT(result != isolate()->heap()->the_hole_value());
+ ASSERT(!result->IsTheHole());
- if (result->IsJSFunction()) {
+ 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
+ // called as functions do.
+ ReceiverToObjectIfRequired(result_handle, object);
+
+ if (result_handle->IsJSFunction()) {
#ifdef ENABLE_DEBUGGER_SUPPORT
// Handle stepping into a function if step into is active.
Debug* debug = isolate()->debug();
if (debug->StepInActive()) {
// Protect the result in a handle as the debugger can allocate and might
// cause GC.
- HandleScope scope(isolate());
- Handle<JSFunction> function(JSFunction::cast(result), isolate());
+ Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate());
debug->HandleStepIn(function, object, fp(), false);
return *function;
}
#endif
- return result;
+ return *result_handle;
}
// Try to find a suitable function delegate for the object at hand.
- result = TryCallAsFunction(result);
- MaybeObject* answer = result;
- if (!result->IsJSFunction()) {
- answer = TypeError("property_not_function", object, name);
- }
- return answer;
+ result_handle = Handle<Object>(TryCallAsFunction(*result_handle));
+ if (result_handle->IsJSFunction()) return *result_handle;
+
+ return TypeError("property_not_function", object, name);
}
@@ -570,8 +588,8 @@
case kStringCharAt:
if (object->IsString()) {
String* string = String::cast(*object);
- // Check that there's the right wrapper in the receiver slot.
- ASSERT(string == JSValue::cast(args[0])->value());
+ // Check there's the right string value or wrapper in the receiver slot.
+ ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
// If we're in the default (fastest) state and the index is
// out of bounds, update the state to record this fact.
if (*extra_ic_state == DEFAULT_STRING_STUB &&
@@ -787,10 +805,6 @@
return TypeError("non_object_property_call", object, key);
}
- if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
- ReceiverToObject(object);
- }
-
if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
int argc = target()->arguments_count();
InLoopFlag in_loop = target()->ic_in_loop();
@@ -805,19 +819,21 @@
#endif
}
}
- Object* result;
- { MaybeObject* maybe_result = Runtime::GetObjectProperty(isolate(),
- object,
- key);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- if (result->IsJSFunction()) return result;
- result = TryCallAsFunction(result);
- MaybeObject* answer = result;
- if (!result->IsJSFunction()) {
- answer = TypeError("property_not_function", object, key);
- }
- return answer;
+
+ 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);
+
+ if (result->IsJSFunction()) return *result;
+ result = Handle<Object>(TryCallAsFunction(*result));
+ if (result->IsJSFunction()) return *result;
+
+ return TypeError("property_not_function", object, key);
}
@@ -1246,7 +1262,7 @@
if (receiver->HasExternalArrayElements()) {
MaybeObject* probe =
isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
- *receiver, false);
+ *receiver, false, kNonStrictMode);
stub = probe->IsFailure() ?
NULL : Code::cast(probe->ToObjectUnchecked());
} else if (receiver->HasIndexedInterceptor()) {
@@ -1397,6 +1413,7 @@
MaybeObject* StoreIC::Store(State state,
+ StrictModeFlag strict_mode,
Handle<Object> object,
Handle<String> name,
Handle<Object> value) {
@@ -1426,10 +1443,11 @@
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
#endif
- Code* target = isolate()->builtins()->builtin(
- Builtins::StoreIC_ArrayLength);
- set_target(target);
- return receiver->SetProperty(*name, *value, NONE);
+ Builtins::Name target = (strict_mode == kStrictMode)
+ ? Builtins::StoreIC_ArrayLength_Strict
+ : Builtins::StoreIC_ArrayLength;
+ set_target(isolate()->builtins()->builtin(target));
+ return receiver->SetProperty(*name, *value, NONE, strict_mode);
}
// Lookup the property locally in the receiver.
@@ -1453,13 +1471,15 @@
// 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 {
@@ -1486,15 +1506,28 @@
// If no inlined store ic was patched, generate a stub for this
// store.
- UpdateCaches(&lookup, state, receiver, name, value);
+ UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
+ } else {
+ // 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.
- if (target() != global_proxy_stub()) {
- set_target(global_proxy_stub());
+ Code* stub = (strict_mode == kStrictMode)
+ ? global_proxy_stub_strict()
+ : global_proxy_stub();
+ if (target() != stub) {
+ set_target(stub);
#ifdef DEBUG
TraceIC("StoreIC", name, state, target());
#endif
@@ -1502,12 +1535,13 @@
}
// Set the property.
- return receiver->SetProperty(*name, *value, NONE);
+ return receiver->SetProperty(*name, *value, NONE, strict_mode);
}
void StoreIC::UpdateCaches(LookupResult* lookup,
State state,
+ StrictModeFlag strict_mode,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value) {
@@ -1529,7 +1563,7 @@
switch (type) {
case FIELD: {
maybe_code = isolate()->stub_cache()->ComputeStoreField(
- *name, *receiver, lookup->GetFieldIndex());
+ *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
break;
}
case MAP_TRANSITION: {
@@ -1539,7 +1573,7 @@
Handle<Map> transition(lookup->GetTransitionMap());
int index = transition->PropertyIndexFor(*name);
maybe_code = isolate()->stub_cache()->ComputeStoreField(
- *name, *receiver, index, *transition);
+ *name, *receiver, index, *transition, strict_mode);
break;
}
case NORMAL: {
@@ -1551,10 +1585,10 @@
JSGlobalPropertyCell* cell =
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
maybe_code = isolate()->stub_cache()->ComputeStoreGlobal(
- *name, *global, cell);
+ *name, *global, cell, strict_mode);
} else {
if (lookup->holder() != *receiver) return;
- maybe_code = isolate()->stub_cache()->ComputeStoreNormal();
+ maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
}
break;
}
@@ -1562,15 +1596,14 @@
if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
if (v8::ToCData<Address>(callback->setter()) == 0) return;
- maybe_code = isolate()->stub_cache()->ComputeStoreCallback(*name,
- *receiver,
- callback);
+ maybe_code = isolate()->stub_cache()->ComputeStoreCallback(
+ *name, *receiver, callback, strict_mode);
break;
}
case INTERCEPTOR: {
ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
- maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor(*name,
- *receiver);
+ maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor(
+ *name, *receiver, strict_mode);
break;
}
default:
@@ -1586,7 +1619,11 @@
set_target(Code::cast(code));
} else if (state == MONOMORPHIC) {
// Only move to megamorphic if the target changes.
- if (target() != Code::cast(code)) set_target(megamorphic_stub());
+ if (target() != Code::cast(code)) {
+ set_target((strict_mode == kStrictMode)
+ ? megamorphic_stub_strict()
+ : megamorphic_stub());
+ }
} else if (state == MEGAMORPHIC) {
// Update the stub cache.
isolate()->stub_cache()->Set(*name,
@@ -1601,6 +1638,7 @@
MaybeObject* KeyedStoreIC::Store(State state,
+ StrictModeFlag strict_mode,
Handle<Object> object,
Handle<Object> key,
Handle<Object> value) {
@@ -1632,11 +1670,11 @@
// 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
@@ -1645,34 +1683,44 @@
ASSERT(!(use_ic && object->IsJSGlobalProxy()));
if (use_ic) {
- Code* stub = generic_stub();
- if (object->IsJSObject()) {
- Handle<JSObject> receiver = Handle<JSObject>::cast(object);
- if (receiver->HasExternalArrayElements()) {
- MaybeObject* probe =
- isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
- *receiver, true);
- stub =
- probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked());
- } else if (state == UNINITIALIZED &&
- key->IsSmi() &&
- receiver->map()->has_fast_elements()) {
- MaybeObject* probe =
- isolate()->stub_cache()->ComputeKeyedStoreSpecialized(*receiver);
- stub =
- probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked());
+ 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 =
+ isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
+ *receiver, true, strict_mode);
+ stub = probe->IsFailure() ?
+ NULL : Code::cast(probe->ToObjectUnchecked());
+ } else if (receiver->HasPixelElements()) {
+ MaybeObject* probe =
+ isolate()->stub_cache()->ComputeKeyedStorePixelArray(
+ *receiver, strict_mode);
+ stub = probe->IsFailure() ?
+ NULL : Code::cast(probe->ToObjectUnchecked());
+ } else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
+ MaybeObject* probe =
+ 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(isolate(), 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) {
@@ -1700,7 +1748,7 @@
switch (type) {
case FIELD: {
maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
- *name, *receiver, lookup->GetFieldIndex());
+ *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
break;
}
case MAP_TRANSITION: {
@@ -1710,7 +1758,7 @@
Handle<Map> transition(lookup->GetTransitionMap());
int index = transition->PropertyIndexFor(*name);
maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
- *name, *receiver, index, *transition);
+ *name, *receiver, index, *transition, strict_mode);
break;
}
// fall through.
@@ -1718,7 +1766,9 @@
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;
}
}
@@ -1733,7 +1783,9 @@
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
@@ -1843,7 +1895,11 @@
ASSERT(args.length() == 3);
StoreIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
- return ic.Store(state, args.at<Object>(0), args.at<String>(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<String>(1),
args.at<Object>(2));
}
@@ -1912,7 +1968,11 @@
ASSERT(args.length() == 3);
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));
}
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698