Chromium Code Reviews| Index: src/ic/accessor-assembler.h |
| diff --git a/src/ic/accessor-assembler.h b/src/ic/accessor-assembler.h |
| index a3fe4ea66225d91f79ada4e4440d21a82685d438..7a39d3566f6f43c680c2e5e5889ef259851984a3 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,13 @@ class AccessorAssembler : public CodeStubAssembler { |
| Node* vector; |
| }; |
| + void LoadGlobalICData(const LoadICParameters* p, ExitPoint* exit_point, |
| + Label* try_handler, Label* miss); |
| + void LoadGlobalICHandler(const LoadICParameters* p, TypeofMode typeof_mode, |
| + ExitPoint* exit_point, Label* miss); |
| + void LoadGlobalICMiss(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 +122,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 +140,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 +189,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 +208,75 @@ 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(out_ != nullptr || var_result_ == nullptr); |
|
Igor Sheludko
2017/02/08 15:26:32
DCHECK_EQ(out != nullptr, var_result != nullptr);
jgruber
2017/02/09 09:23:42
Done.
|
| + } |
| + |
| + template <class... TArgs> |
| + void ReturnRuntime(Runtime::FunctionId function, Node* context, |
|
Igor Sheludko
2017/02/08 15:26:32
ReturnCallRuntime
jgruber
2017/02/09 09:23:42
Done.
|
| + TArgs... args) { |
| + if (IsDirect()) { |
| + asm_->TailCallRuntime(function, context, args...); |
| + } else { |
| + IndirectReturn(asm_->CallRuntime(function, context, args...)); |
| + } |
| + } |
| + |
| + template <class... TArgs> |
| + void ReturnStub(Callable const& callable, Node* context, TArgs... args) { |
|
Igor Sheludko
2017/02/08 15:26:32
ReturnCallStub
jgruber
2017/02/09 09:23:42
Done.
|
| + if (IsDirect()) { |
| + asm_->TailCallStub(callable, context, args...); |
| + } else { |
| + IndirectReturn(asm_->CallStub(callable, context, args...)); |
| + } |
| + } |
| + |
| + template <class... TArgs> |
| + void ReturnStub(const CallInterfaceDescriptor& descriptor, Node* target, |
|
Igor Sheludko
2017/02/08 15:26:32
ReturnCallStub
jgruber
2017/02/09 09:23:42
Done.
|
| + 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; } |
| + bool IsIndirect() const { return !IsDirect(); } |
|
Igor Sheludko
2017/02/08 15:26:32
I'd just leave IsDirect()
jgruber
2017/02/09 09:23:42
Done.
|
| + |
| + 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 |