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

Unified Diff: src/code-stubs-hydrogen.cc

Issue 767743002: Hydrogen code stubs for vector-based ICs. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Patch One. Created 6 years, 1 month 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 | « no previous file | src/hydrogen.cc » ('j') | src/hydrogen-instructions.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stubs-hydrogen.cc
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index fca1e293f8c315f872a0a79143fa70838695d540..807f8960b72a279c09f8fd7998dfe109e2c7e19f 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -8,6 +8,7 @@
#include "src/code-stubs.h"
#include "src/field-index.h"
#include "src/hydrogen.h"
+#include "src/ic/ic.h"
#include "src/lithium.h"
namespace v8 {
@@ -99,6 +100,21 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
HValue* shared_info,
HValue* native_context);
+ // Tail calls handler found at array[index].
+ void TailCallHandler(HValue* receiver, HValue* name, HValue* array,
+ HValue* index, HValue* slot, HValue* vector);
+
+ // Tail calls handler_code.
+ void TailCallHandler(HValue* receiver, HValue* name, HValue* slot,
+ HValue* vector, HValue* handler_code);
+
+ void TailCallMiss(HValue* receiver, HValue* name, HValue* slot,
+ HValue* vector, bool keyed_load);
+
+ // Handle MONOMORPHIC and POLYMORPHIC LoadIC and KeyedLoadIC cases.
+ void HandleArrayCases(HValue* array, HValue* receiver, HValue* name,
+ HValue* slot, HValue* vector, bool keyed_load);
+
private:
HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder);
HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder,
@@ -2003,11 +2019,137 @@ Handle<Code> KeyedLoadGenericStub::GenerateCode() {
}
+void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name,
+ HValue* array, HValue* index,
+ HValue* slot, HValue* vector) {
+ HValue* handler_code =
+ Add<HLoadKeyed>(array, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+ TailCallHandler(receiver, name, slot, vector, handler_code);
+}
+
+
+void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name,
+ HValue* slot, HValue* vector,
+ HValue* handler_code) {
+ VectorLoadICDescriptor descriptor(isolate());
+ HValue* op_vals[] = {context(), receiver, name, slot, vector};
+ // We never return here, it is a tail call.
Jakob Kummerow 2014/12/02 08:43:06 nit: I'd move this comment after the Add<...>. If
mvstanton 2014/12/03 11:48:30 Thanks, sounds like a good idea. I tried approxima
+ Add<HCallWithDescriptor>(handler_code, 0, descriptor,
+ Vector<HValue*>(op_vals, 5), TAIL_CALL);
+}
+
+
+void CodeStubGraphBuilderBase::TailCallMiss(HValue* receiver, HValue* name,
+ HValue* slot, HValue* vector,
+ bool keyed_load) {
+ DCHECK(FLAG_vector_ics);
+ // We never return here, it is a tail call.
Jakob Kummerow 2014/12/02 08:43:06 same here
mvstanton 2014/12/03 11:48:30 Done.
+ Add<HTailCallThroughMegamorphicCache>(
+ receiver, name, slot, vector,
+ HTailCallThroughMegamorphicCache::ComputeFlags(keyed_load, true));
+}
+
+
+void CodeStubGraphBuilderBase::HandleArrayCases(HValue* array, HValue* receiver,
+ HValue* name, HValue* slot,
+ HValue* vector,
+ bool keyed_load) {
+ HValue* length = AddLoadFixedArrayLength(array, static_cast<HValue*>(NULL));
+ HValue* receiver_map = AddLoadMap(receiver, static_cast<HValue*>(NULL));
+ IfBuilder mono_checker(this);
Jakob Kummerow 2014/12/02 08:43:06 Naming suggestion: if you name this guy "if_monomo
mvstanton 2014/12/03 11:48:30 Done.
+ HValue* mono_length =
+ Add<HConstant>(static_cast<int32_t>(keyed_load ? 3 : 2));
+ mono_checker.If<HCompareNumericAndBranch>(length, mono_length, Token::EQ);
+ mono_checker.Then();
+ {
+ // Compare map.
+ HValue* start =
+ keyed_load ? graph()->GetConstant1() : graph()->GetConstant0();
+ HValue* array_map = Add<HLoadKeyed>(
+ array, start, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+ IfBuilder correct_map_checker(this);
+ correct_map_checker.If<HCompareObjectEqAndBranch>(receiver_map, array_map);
+ correct_map_checker.Then();
+ {
+ HValue* handler_index = keyed_load
+ ? Add<HConstant>(static_cast<int32_t>(2))
Jakob Kummerow 2014/12/02 08:43:06 nit: Drop the static_cast, it's cleaner.
mvstanton 2014/12/03 11:48:29 Done.
mvstanton 2014/12/03 11:48:30 Done. I reformulated this code a bit too, noticing
+ : graph()->GetConstant1();
+ TailCallHandler(receiver, name, array, handler_index, slot, vector);
+ }
+ correct_map_checker.Else();
+ { TailCallMiss(receiver, name, slot, vector, keyed_load); }
+ correct_map_checker.End();
+ }
+ mono_checker.Else();
+ {
+ // It is polymorphic.
+ HValue* increment_amount = Add<HConstant>(2);
+ LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement,
+ increment_amount);
+ HValue* start =
+ keyed_load ? graph()->GetConstant1() : graph()->GetConstant0();
+ HValue* key = builder.BeginBody(start, length, Token::LT);
+ {
+ HValue* array_map = Add<HLoadKeyed>(
+ array, key, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+ IfBuilder correct_map_checker(this);
+ correct_map_checker.If<HCompareObjectEqAndBranch>(receiver_map,
+ array_map);
+ correct_map_checker.Then();
+ {
+ HValue* one = graph()->GetConstant1();
+ HValue* index = AddUncasted<HAdd>(key, one);
+ TailCallHandler(receiver, name, array, index, slot, vector);
+ }
+ }
+ builder.EndBody();
+
+ TailCallMiss(receiver, name, slot, vector, keyed_load);
+ }
+ mono_checker.End();
+}
+
+
template <>
HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() {
HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex);
- Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER);
- return receiver;
+ HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex);
+ HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex);
+ HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex);
+
+ // Are we monomorphic?
Jakob Kummerow 2014/12/02 08:43:06 nit: s/Are we foo/Is the IC in foo state/, and ple
mvstanton 2014/12/03 11:48:30 Done.
+ HValue* feedback =
+ Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+ IfBuilder array_checker(this);
+ array_checker.If<HCompareMap>(feedback,
Jakob Kummerow 2014/12/02 08:43:06 This map check bakes in the assumption that the fe
mvstanton 2014/12/03 11:48:30 Yes indeed, that is why we have a pile of symbols
+ isolate()->factory()->fixed_array_map());
+ array_checker.Then();
+ {
+ Add<HCheckHeapObject>(receiver);
Jakob Kummerow 2014/12/02 08:43:06 Ugh. Hydrogen's ugly warts. HCheckHeapObject shoul
mvstanton 2014/12/03 11:48:30 Oh yeah, creepy. Okay, I've turned the HCheckHeapO
Jakob Kummerow 2014/12/03 13:22:17 That's fine, but I didn't mean to imply you should
+ HandleArrayCases(feedback, receiver, name, slot, vector, false);
+ }
+ array_checker.Else();
+ {
+ // Are we megamorphic?
+ IfBuilder mega_checker(this);
+ HConstant* megamorphic_symbol =
+ Add<HConstant>(isolate()->factory()->megamorphic_symbol());
+ mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol);
+ mega_checker.Then();
+ {
+ // Probe the stub cache.
+ Add<HTailCallThroughMegamorphicCache>(
+ receiver, name, slot, vector,
+ HTailCallThroughMegamorphicCache::ComputeFlags(false, false));
+ }
+ mega_checker.End();
+
+ TailCallMiss(receiver, name, slot, vector, false);
+ }
+ array_checker.End();
+
+ // We never get here.
+ return graph()->GetConstant0();
}
@@ -2017,8 +2159,91 @@ Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); }
template <>
HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() {
HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex);
- Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER);
- return receiver;
+ HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex);
+ HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex);
+ HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex);
+ HConstant* zero = graph()->GetConstant0();
+
+ // Are we monomorphic?
+ HValue* feedback =
+ Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+ IfBuilder array_checker(this);
+ array_checker.If<HCompareMap>(feedback,
+ isolate()->factory()->fixed_array_map());
+ array_checker.Then();
+ {
+ // Deal with the key. If feedback[0] is 0, then we are dealing with element
+ // handlers. Otherwise, it's a string, verify that name matches.
+ HValue* recorded_name = Add<HLoadKeyed>(
+ feedback, zero, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+
+ IfBuilder recorded_name_is_zero(this);
+ recorded_name_is_zero.If<HCompareNumericAndBranch>(recorded_name, zero,
+ Token::EQ);
+ recorded_name_is_zero.Then();
+ {
+ // TODO(mvstanton): is this necessary? Anyway, I should call the
+ // miss handler directly and not let the bailout mechanism run.
+ Add<HCheckSmi>(name);
+ }
+ recorded_name_is_zero.Else();
+ {
+ IfBuilder strings_match(this);
+ strings_match.IfNot<HCompareObjectEqAndBranch>(name, recorded_name);
+ strings_match.Then();
+ TailCallMiss(receiver, name, slot, vector, true);
+ strings_match.End();
+ }
+ recorded_name_is_zero.End();
+
+ Add<HCheckHeapObject>(receiver);
+ HandleArrayCases(feedback, receiver, name, slot, vector, true);
+ }
+ array_checker.Else();
+ {
+ // Are we megamorphic?
+ IfBuilder mega_checker(this);
+ HConstant* megamorphic_symbol =
+ Add<HConstant>(isolate()->factory()->megamorphic_symbol());
+ mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol);
+ mega_checker.Then();
+ {
+ // HTailCallThroughMegamorphicCache expects name to be a string.
+ // TODO(mvstanton): I don't understand why I need this check. How does it
+ // work without --vector-ics on? Because there isn't a check on the name
+ // in that case right?
Jakob Kummerow 2014/12/02 08:43:06 KeyedLoadIC currently doesn't support megamorphic
mvstanton 2014/12/03 11:48:30 Wow...the overloaded megamorphic_stub() method in
Jakob Kummerow 2014/12/03 13:22:17 Acknowledged.
+ Add<HCheckHeapObject>(name);
+ // Probe the stub cache.
+ Add<HTailCallThroughMegamorphicCache>(
+ receiver, name, slot, vector,
+ HTailCallThroughMegamorphicCache::ComputeFlags(true, false));
+ }
+ mega_checker.End();
+
+ // Are we generic?
+ IfBuilder generic_checker(this);
+ HConstant* generic_symbol =
+ Add<HConstant>(isolate()->factory()->generic_symbol());
+ generic_checker.If<HCompareObjectEqAndBranch>(feedback, generic_symbol);
+ generic_checker.Then();
+ {
+ // Tail-call to the generic KeyedLoadIC, treating it like a handler.
+ Handle<Code> stub = KeyedLoadIC::generic_stub(isolate());
+ HValue* constant_stub = Add<HConstant>(stub);
+ LoadDescriptor descriptor(isolate());
+ HValue* op_vals[] = {context(), receiver, name};
+ // We never return here, it is a tail call.
+ Add<HCallWithDescriptor>(constant_stub, 0, descriptor,
+ Vector<HValue*>(op_vals, 3), TAIL_CALL);
+ }
+ generic_checker.End();
+
+ TailCallMiss(receiver, name, slot, vector, true);
+ }
+ array_checker.End();
+
+ // We never get here.
+ return zero;
}
@@ -2034,14 +2259,15 @@ Handle<Code> MegamorphicLoadStub::GenerateCode() {
template <>
HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() {
- // The return address is on the stack.
HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex);
HValue* name = GetParameter(LoadDescriptor::kNameIndex);
+ // We shouldn't generate this when FLAG_vector_ics is true because the
+ // megamorphic case is handled as part of the default stub.
+ DCHECK(!FLAG_vector_ics);
+
// Probe the stub cache.
- Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
- Code::ComputeHandlerFlags(Code::LOAD_IC));
- Add<HTailCallThroughMegamorphicCache>(receiver, name, flags);
+ Add<HTailCallThroughMegamorphicCache>(receiver, name);
// We never continue.
return graph()->GetConstant0();
« no previous file with comments | « no previous file | src/hydrogen.cc » ('j') | src/hydrogen-instructions.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698