Index: src/ic/accessor-assembler.h |
diff --git a/src/ic/accessor-assembler.h b/src/ic/accessor-assembler.h |
index a3fe4ea66225d91f79ada4e4440d21a82685d438..1127ea5f6b82be95fb4c8a2c69840697fd2db0ef 100644 |
--- a/src/ic/accessor-assembler.h |
+++ b/src/ic/accessor-assembler.h |
@@ -14,6 +14,8 @@ namespace compiler { |
class CodeAssemblerState; |
} |
+class ExitPoint; |
+ |
class AccessorAssembler : public CodeStubAssembler { |
public: |
typedef compiler::Node Node; |
@@ -49,7 +51,6 @@ class AccessorAssembler : public CodeStubAssembler { |
return StubCacheSecondaryOffset(name, map); |
} |
- protected: |
struct LoadICParameters { |
LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot, |
Node* vector) |
@@ -66,6 +67,15 @@ class AccessorAssembler : public CodeStubAssembler { |
Node* vector; |
}; |
+ void LoadGlobalIC_TryPropertyCellCase( |
+ Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler, |
+ Label* miss, ParameterMode slot_mode = SMI_PARAMETERS); |
+ void LoadGlobalIC_TryHandlerCase(const LoadICParameters* p, |
+ TypeofMode typeof_mode, |
+ ExitPoint* exit_point, Label* miss); |
+ void LoadGlobalIC_MissCase(const LoadICParameters* p, ExitPoint* exit_point); |
+ |
+ protected: |
struct StoreICParameters : public LoadICParameters { |
StoreICParameters(Node* context, Node* receiver, Node* name, Node* value, |
Node* slot, Node* vector) |
@@ -114,12 +124,14 @@ class AccessorAssembler : public CodeStubAssembler { |
void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder, |
Node* smi_handler, Label* miss, |
+ ExitPoint* exit_point, |
ElementSupport support_elements); |
void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler, |
Variable* var_holder, |
Variable* var_smi_handler, |
Label* if_smi_handler, Label* miss, |
+ ExitPoint* exit_point, |
bool throw_reference_error_if_nonexistent); |
Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler, |
@@ -130,7 +142,7 @@ class AccessorAssembler : public CodeStubAssembler { |
// LoadGlobalIC implementation. |
void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler, |
- Label* miss, |
+ Label* miss, ExitPoint* exit_point, |
bool throw_reference_error_if_nonexistent); |
// StoreIC implementation. |
@@ -179,7 +191,7 @@ class AccessorAssembler : public CodeStubAssembler { |
Node* key, Node* is_jsarray_condition, Label* if_hole, |
Label* rebox_double, Variable* var_double_value, |
Label* unimplemented_elements_kind, Label* out_of_bounds, |
- Label* miss); |
+ Label* miss, ExitPoint* exit_point); |
void CheckPrototype(Node* prototype_cell, Node* name, Label* miss); |
void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss); |
@@ -198,6 +210,74 @@ class AccessorAssembler : public CodeStubAssembler { |
Label* if_miss); |
}; |
+// Abstraction over direct and indirect exit points. Direct exits correspond to |
+// tailcalls and Return, while indirect exits store the result in a variable |
+// and then jump to an exit label. |
+class ExitPoint { |
+ private: |
+ typedef compiler::Node Node; |
+ typedef compiler::CodeAssemblerLabel CodeAssemblerLabel; |
+ typedef compiler::CodeAssemblerVariable CodeAssemblerVariable; |
+ |
+ public: |
+ explicit ExitPoint(CodeStubAssembler* assembler) |
+ : ExitPoint(assembler, nullptr, nullptr) {} |
+ ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out, |
+ CodeAssemblerVariable* var_result) |
+ : out_(out), var_result_(var_result), asm_(assembler) { |
+ DCHECK_EQ(out != nullptr, var_result != nullptr); |
+ } |
+ |
+ template <class... TArgs> |
+ void ReturnCallRuntime(Runtime::FunctionId function, Node* context, |
+ TArgs... args) { |
+ if (IsDirect()) { |
+ asm_->TailCallRuntime(function, context, args...); |
+ } else { |
+ IndirectReturn(asm_->CallRuntime(function, context, args...)); |
+ } |
+ } |
+ |
+ template <class... TArgs> |
+ void ReturnCallStub(Callable const& callable, Node* context, TArgs... args) { |
+ if (IsDirect()) { |
+ asm_->TailCallStub(callable, context, args...); |
+ } else { |
+ IndirectReturn(asm_->CallStub(callable, context, args...)); |
+ } |
+ } |
+ |
+ template <class... TArgs> |
+ void ReturnCallStub(const CallInterfaceDescriptor& descriptor, Node* target, |
+ Node* context, TArgs... args) { |
+ if (IsDirect()) { |
+ asm_->TailCallStub(descriptor, target, context, args...); |
+ } else { |
+ IndirectReturn(asm_->CallStub(descriptor, target, context, args...)); |
+ } |
+ } |
+ |
+ void Return(Node* const result) { |
+ if (IsDirect()) { |
+ asm_->Return(result); |
+ } else { |
+ IndirectReturn(result); |
+ } |
+ } |
+ |
+ bool IsDirect() const { return out_ == nullptr; } |
+ |
+ private: |
+ void IndirectReturn(Node* const result) { |
+ var_result_->Bind(result); |
+ asm_->Goto(out_); |
+ } |
+ |
+ CodeAssemblerLabel* const out_; |
+ CodeAssemblerVariable* const var_result_; |
+ CodeStubAssembler* const asm_; |
+}; |
+ |
} // namespace internal |
} // namespace v8 |