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

Unified Diff: src/ic.cc

Issue 172523002: Create a function call IC (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 6 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
« src/ic.h ('K') | « 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
diff --git a/src/ic.cc b/src/ic.cc
index 2607bb3b68d53405be03865fe60538dea4e8b9e0..8a352f0b85e384549eb078b72c851180ad172ae3 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -91,9 +91,11 @@ void IC::TraceIC(const char* type,
}
JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
ExtraICState extra_state = new_target->extra_ic_state();
- const char* modifier =
- GetTransitionMarkModifier(
- KeyedStoreIC::GetKeyedAccessStoreMode(extra_state));
+ const char* modifier = "";
+ if (new_target->kind() != Code::CALL_IC) {
Toon Verwaest 2014/03/10 13:50:44 Isn't this only relevant for KEYED_STORE_IC?
mvstanton 2014/03/20 15:51:53 Done.
+ modifier = GetTransitionMarkModifier(
+ KeyedStoreIC::GetKeyedAccessStoreMode(extra_state));
+ }
PrintF(" (%c->%c%s)",
TransitionMarkFromState(state()),
TransitionMarkFromState(new_state),
@@ -422,6 +424,7 @@ void IC::Clear(Isolate* isolate, Address address) {
case Code::STORE_IC: return StoreIC::Clear(isolate, address, target);
case Code::KEYED_STORE_IC:
return KeyedStoreIC::Clear(isolate, address, target);
+ case Code::CALL_IC: return CallIC::Clear(address, target);
case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target);
case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target);
case Code::BINARY_OP_IC:
@@ -434,6 +437,11 @@ void IC::Clear(Isolate* isolate, Address address) {
}
+void CallIC::Clear(Address address, Code* target) {
+ // TODO(mvstanton): What does it mean to clear this hybrid?
+}
+
+
void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) {
if (IsCleared(target)) return;
// Make sure to also clear the map used in inline fast cases. If we
@@ -1264,6 +1272,37 @@ MaybeObject* StoreIC::Store(Handle<Object> object,
}
+void CallIC::State::Print(StringStream* stream) const {
+ stream->Add("(args(%d), ",
+ argc_);
+ stream->Add("%s, ",
+ call_as_method_ ? "METHOD" : "FUNCTION");
+ stream->Add("%s, ",
+ monomorphic_ ? "MONOMORPHIC" : "NOT_MONOMORPHIC");
+ stream->Add("%s, ",
+ args_match_ ? "args_match" : "args_dont_match");
+ stream->Add("%s)",
+ strict_native_ ? "strict_or_native" : "not_strict_or_native");
+}
+
+
+void CallIC::GenerateNormal(MacroAssembler* masm, int argc,
+ bool call_as_method) {
+ CallICStub stub(State(argc, call_as_method, false, true, false));
+ stub.GetCode(masm->isolate());
+}
+
+
+Handle<Code> CallIC::initialize_stub(Isolate* isolate,
+ int argc,
+ bool call_as_method) {
+ CallICStub stub(State(argc, call_as_method, false, true, false));
+ ASSERT(stub.call_as_method() == call_as_method);
+ Handle<Code> code = stub.GetCode(isolate);
+ return code;
+}
+
+
Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
StrictModeFlag strict_mode) {
ExtraICState extra_state = ComputeExtraICState(strict_mode);
@@ -1725,6 +1764,111 @@ MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
}
+CallIC::State::State(ExtraICState extra_ic_state) {
+ argc_ = ArgBits::decode(extra_ic_state);
+ call_as_method_ = CallAsMethodBits::decode(extra_ic_state);
+ monomorphic_ = MonomorphicBits::decode(extra_ic_state);
+ args_match_ = ArgsMatchBits::decode(extra_ic_state);
+ strict_native_ = StrictNativeBits::decode(extra_ic_state);
+}
+
+
+ExtraICState CallIC::State::GetExtraICState() const {
+ ExtraICState extra_ic_state =
+ ArgBits::encode(argc_) |
+ CallAsMethodBits::encode(call_as_method_) |
+ MonomorphicBits::encode(monomorphic_) |
+ ArgsMatchBits::encode(args_match_) |
+ StrictNativeBits::encode(strict_native_);
+ return extra_ic_state;
+}
+
+
+void CallIC::PatchMegamorphic(int arg_count, bool call_as_method) {
+ CallICStub stub(State(arg_count, call_as_method));
+ set_target(*stub.GetCode(isolate()));
+ TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
+}
+
+
+void CallIC::HandleMiss(Handle<Object> receiver,
+ Handle<Object> function,
+ Handle<FixedArray> vector,
+ Handle<Smi> slot) {
+ State state(target()->extra_ic_state());
+ Object* feedback = vector->get(slot->value());
+ if (feedback->IsJSFunction()) {
Toon Verwaest 2014/03/10 13:50:44 Shouldn't this be feedback->IsJSFunction() && func
mvstanton 2014/03/20 15:51:53 I went ahead and just returned without changing an
+ // We are going megamorphic, only if we were given a real function,
+ // otherwise the slow path will be taken.
Toon Verwaest 2014/03/10 13:50:44 Weird sentence
mvstanton 2014/03/20 15:51:53 Removed.
+ vector->set(slot->value(),
+ *TypeFeedbackInfo::MegamorphicSentinel(isolate()));
+ // Do we need to patch? Only if we currently don't have the default stub
Toon Verwaest 2014/03/10 13:50:44 We only need to patch if ...
mvstanton 2014/03/20 15:51:53 Done.
+ // in place.
+ if (state.monomorphic()) {
+ PatchMegamorphic(state.arg_count(), state.call_as_method());
+ }
+ } else {
+ // If we came here feedback must be the uninitialized sentinel,
+ // and we are going monomorphic.
+ ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()));
+
+ // Ugh. Do nothing if the function isn't a function, the slow path is taken.
Toon Verwaest 2014/03/10 13:50:44 Remove ugh.
mvstanton 2014/03/20 15:51:53 Done.
+ if (!function->IsJSFunction()) {
+ // If we don't have a function, just go megamorphic.
+ vector->set(slot->value(),
+ *TypeFeedbackInfo::MegamorphicSentinel(isolate()));
+ if (state.monomorphic()) {
+ PatchMegamorphic(state.arg_count(), state.call_as_method());
+ }
+ } else {
+ vector->set(slot->value(), *function);
+ SharedFunctionInfo* shared = Handle<JSFunction>::cast(function)->shared();
+ // Choose the right monomorphic handler
+ bool arg_count_match =
+ shared->formal_parameter_count() == state.arg_count();
+ bool strict_or_native = shared->language_mode() == STRICT_MODE ||
+ shared->native();
+
+ bool must_patch = false;
+ if (state.monomorphic()) {
+ // We are here because we are in snapshot code that went monomorphic but
+ // now our cell is cleared because we are running an application.
+ // Ideally we can just patch the cell and return.
Toon Verwaest 2014/03/10 13:50:44 Are we sure that we can only get here because of s
mvstanton 2014/03/20 15:51:53 I went to objects-visiting-inl.h and make sure tha
+ must_patch = arg_count_match != state.args_match() ||
+ strict_or_native != state.strict_native();
+ } else {
+ // We need to patch only if attributes differ from the monomorphic case
+ // built into the generic stub (with arg_count_match = true and
+ // !strict_or_native)
+ must_patch = !arg_count_match || strict_or_native;
+ }
+
+ Handle<String> name;
Toon Verwaest 2014/03/10 13:50:44 Don't you want to initialize this to something lik
mvstanton 2014/03/20 15:51:53 Yes, I could simplify that even more.
+ Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
+ if (js_function->shared()->name()->IsString()) {
+ name = Handle<String>(String::cast(js_function->shared()->name()),
+ isolate());
+ }
+
+ if (must_patch) {
+ CallICStub stub(State(state.arg_count(),
+ state.call_as_method(),
+ true,
+ arg_count_match,
+ strict_or_native));
+ set_target(*stub.GetCode(isolate()));
+#ifdef DEBUG
+ const char *str = state.monomorphic()
+ ? "CallIC (snapshot miss)"
+ : "CallIC";
+#endif
+ TRACE_IC(str, name);
+ }
+ }
+ }
+}
+
+
#undef TRACE_IC
@@ -1733,6 +1877,19 @@ MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
//
// Used from ic-<arch>.cc.
+RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 4);
+ CallIC ic(isolate);
+ Handle<Object> receiver = args.at<Object>(0);
+ Handle<Object> function = args.at<Object>(1);
+ Handle<FixedArray> vector = args.at<FixedArray>(2);
+ Handle<Smi> slot = args.at<Smi>(3);
+ ic.HandleMiss(receiver, function, vector, slot);
+ return *function;
+}
+
+
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
HandleScope scope(isolate);
« src/ic.h ('K') | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698