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

Unified Diff: src/ic.cc

Issue 2280007: Extend CallIC to support non-constant names.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 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/log.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 4791)
+++ src/ic.cc (working copy)
@@ -152,11 +152,13 @@
// to prototype check failure.
int index = map->IndexInCodeCache(name, target);
if (index >= 0) {
- // For keyed load/store, the most likely cause of cache failure is
+ // For keyed load/store/call, the most likely cause of cache failure is
// that the key has changed. We do not distinguish between
// prototype and non-prototype failures for keyed access.
Code::Kind kind = target->kind();
- if (kind == Code::KEYED_LOAD_IC || kind == Code::KEYED_STORE_IC) {
+ if (kind == Code::KEYED_LOAD_IC ||
+ kind == Code::KEYED_STORE_IC ||
+ kind == Code::KEYED_CALL_IC) {
return MONOMORPHIC;
}
@@ -196,9 +198,9 @@
Failure* IC::TypeError(const char* type,
Handle<Object> object,
- Handle<String> name) {
+ Handle<Object> key) {
HandleScope scope;
- Handle<Object> args[2] = { name, object };
+ Handle<Object> args[2] = { key, object };
Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2));
return Top::Throw(*error);
}
@@ -224,6 +226,7 @@
case Code::STORE_IC: return StoreIC::Clear(address, target);
case Code::KEYED_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: return; // Clearing these is tricky and does not
// make any performance difference.
default: UNREACHABLE();
@@ -231,12 +234,13 @@
}
-void CallIC::Clear(Address address, Code* target) {
+void CallICBase::Clear(Address address, Code* target) {
State state = target->ic_state();
- InLoopFlag in_loop = target->ic_in_loop();
if (state == UNINITIALIZED) return;
Code* code =
- StubCache::FindCallInitialize(target->arguments_count(), in_loop);
+ StubCache::FindCallInitialize(target->arguments_count(),
+ target->ic_in_loop(),
+ target->kind());
SetTargetAtAddress(address, code);
}
@@ -364,7 +368,7 @@
}
-Object* CallIC::TryCallAsFunction(Object* object) {
+Object* CallICBase::TryCallAsFunction(Object* object) {
HandleScope scope;
Handle<Object> target(object);
Handle<Object> delegate = Execution::GetFunctionDelegate(target);
@@ -383,7 +387,7 @@
return *delegate;
}
-void CallIC::ReceiverToObject(Handle<Object> object) {
+void CallICBase::ReceiverToObject(Handle<Object> object) {
HandleScope scope;
Handle<Object> receiver(object);
@@ -396,9 +400,9 @@
}
-Object* CallIC::LoadFunction(State state,
- Handle<Object> object,
- Handle<String> name) {
+Object* CallICBase::LoadFunction(State state,
+ Handle<Object> object,
+ Handle<String> name) {
// If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case.
if (object->IsUndefined() || object->IsNull()) {
@@ -481,7 +485,7 @@
}
-void CallIC::UpdateCaches(LookupResult* lookup,
+void CallICBase::UpdateCaches(LookupResult* lookup,
State state,
Handle<Object> object,
Handle<String> name) {
@@ -497,16 +501,21 @@
// This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay
// setting the monomorphic state.
- code = StubCache::ComputeCallPreMonomorphic(argc, in_loop);
+ code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
} else if (state == MONOMORPHIC) {
- code = StubCache::ComputeCallMegamorphic(argc, in_loop);
+ code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
} else {
// Compute monomorphic stub.
switch (lookup->type()) {
case FIELD: {
int index = lookup->GetFieldIndex();
- code = StubCache::ComputeCallField(argc, in_loop, *name, *object,
- lookup->holder(), index);
+ code = StubCache::ComputeCallField(argc,
+ in_loop,
+ kind_,
+ *name,
+ *object,
+ lookup->holder(),
+ index);
break;
}
case CONSTANT_FUNCTION: {
@@ -514,8 +523,13 @@
// call; used for rewriting to monomorphic state and making sure
// that the code stub is in the stub cache.
JSFunction* function = lookup->GetConstantFunction();
- code = StubCache::ComputeCallConstant(argc, in_loop, *name, *object,
- lookup->holder(), function);
+ code = StubCache::ComputeCallConstant(argc,
+ in_loop,
+ kind_,
+ *name,
+ *object,
+ lookup->holder(),
+ function);
break;
}
case NORMAL: {
@@ -530,6 +544,7 @@
JSFunction* function = JSFunction::cast(cell->value());
code = StubCache::ComputeCallGlobal(argc,
in_loop,
+ kind_,
*name,
*receiver,
global,
@@ -541,13 +556,20 @@
// property must be found in the receiver for the stub to be
// applicable.
if (lookup->holder() != *receiver) return;
- code = StubCache::ComputeCallNormal(argc, in_loop, *name, *receiver);
+ code = StubCache::ComputeCallNormal(argc,
+ in_loop,
+ kind_,
+ *name,
+ *receiver);
}
break;
}
case INTERCEPTOR: {
ASSERT(HasInterceptorGetter(lookup->holder()));
- code = StubCache::ComputeCallInterceptor(argc, *name, *object,
+ code = StubCache::ComputeCallInterceptor(argc,
+ kind_,
+ *name,
+ *object,
lookup->holder());
break;
}
@@ -569,11 +591,44 @@
}
#ifdef DEBUG
- TraceIC("CallIC", name, state, target(), in_loop ? " (in-loop)" : "");
+ TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
+ name, state, target(), in_loop ? " (in-loop)" : "");
#endif
}
+Object* KeyedCallIC::LoadFunction(State state,
+ Handle<Object> object,
+ Handle<Object> key) {
+ if (key->IsSymbol()) {
+ return CallICBase::LoadFunction(state, object, Handle<String>::cast(key));
+ }
+
+ if (object->IsUndefined() || object->IsNull()) {
+ return TypeError("non_object_property_call", object, key);
+ }
+
+ if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
+ ReceiverToObject(object);
+ } else {
+ if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
+ int argc = target()->arguments_count();
+ InLoopFlag in_loop = target()->ic_in_loop();
+ Object* code = StubCache::ComputeCallMegamorphic(
+ argc, in_loop, Code::KEYED_CALL_IC);
+ if (!code->IsFailure()) {
+ set_target(Code::cast(code));
+ }
+ }
+ }
+ Object* result = Runtime::GetObjectProperty(object, key);
+ if (result->IsJSFunction()) return result;
+ result = TryCallAsFunction(result);
+ return result->IsJSFunction() ?
+ result : TypeError("property_not_function", object, key);
+}
+
+
Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
// If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case.
@@ -1293,7 +1348,22 @@
// Static IC stub generators.
//
-// Used from ic_<arch>.cc.
+static Object* CompileFunction(Object* result,
+ Handle<Object> object,
+ InLoopFlag in_loop) {
+ // Compile now with optimization.
+ HandleScope scope;
+ Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result));
+ if (in_loop == IN_LOOP) {
+ CompileLazyInLoop(function, object, CLEAR_EXCEPTION);
+ } else {
+ CompileLazy(function, object, CLEAR_EXCEPTION);
+ }
+ return *function;
+}
+
+
+// Used from ic-<arch>.cc.
Object* CallIC_Miss(Arguments args) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
@@ -1312,21 +1382,27 @@
if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
return result;
}
+ return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop());
+}
- // Compile now with optimization.
- HandleScope scope;
- Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result));
- InLoopFlag in_loop = ic.target()->ic_in_loop();
- if (in_loop == IN_LOOP) {
- CompileLazyInLoop(function, args.at<Object>(0), CLEAR_EXCEPTION);
- } else {
- CompileLazy(function, args.at<Object>(0), CLEAR_EXCEPTION);
+
+// Used from ic-<arch>.cc.
+Object* KeyedCallIC_Miss(Arguments args) {
+ NoHandleAllocation na;
+ ASSERT(args.length() == 2);
+ KeyedCallIC ic;
+ IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
+ Object* result =
+ ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
+
+ if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
+ return result;
}
- return *function;
+ return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop());
}
-// Used from ic_<arch>.cc.
+// Used from ic-<arch>.cc.
Object* LoadIC_Miss(Arguments args) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
@@ -1336,7 +1412,7 @@
}
-// Used from ic_<arch>.cc
+// Used from ic-<arch>.cc
Object* KeyedLoadIC_Miss(Arguments args) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
@@ -1346,7 +1422,7 @@
}
-// Used from ic_<arch>.cc.
+// Used from ic-<arch>.cc.
Object* StoreIC_Miss(Arguments args) {
NoHandleAllocation na;
ASSERT(args.length() == 3);
@@ -1404,7 +1480,7 @@
}
-// Used from ic_<arch>.cc.
+// Used from ic-<arch>.cc.
Object* KeyedStoreIC_Miss(Arguments args) {
NoHandleAllocation na;
ASSERT(args.length() == 3);
« no previous file with comments | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698