aboutsummaryrefslogtreecommitdiff
path: root/src/ic/accessor-assembler.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ic/accessor-assembler.h')
-rw-r--r--src/ic/accessor-assembler.h284
1 files changed, 284 insertions, 0 deletions
diff --git a/src/ic/accessor-assembler.h b/src/ic/accessor-assembler.h
new file mode 100644
index 00000000..9bc2873f
--- /dev/null
+++ b/src/ic/accessor-assembler.h
@@ -0,0 +1,284 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_SRC_IC_ACCESSOR_ASSEMBLER_H_
+#define V8_SRC_IC_ACCESSOR_ASSEMBLER_H_
+
+#include "src/code-stub-assembler.h"
+
+namespace v8 {
+namespace internal {
+
+namespace compiler {
+class CodeAssemblerState;
+}
+
+class ExitPoint;
+
+class AccessorAssembler : public CodeStubAssembler {
+ public:
+ typedef compiler::Node Node;
+
+ explicit AccessorAssembler(compiler::CodeAssemblerState* state)
+ : CodeStubAssembler(state) {}
+
+ void GenerateLoadIC();
+ void GenerateLoadField();
+ void GenerateLoadICTrampoline();
+ void GenerateKeyedLoadIC();
+ void GenerateKeyedLoadICTrampoline();
+ void GenerateKeyedLoadIC_Megamorphic();
+ void GenerateStoreIC();
+ void GenerateStoreICTrampoline();
+
+ void GenerateLoadICProtoArray(bool throw_reference_error_if_nonexistent);
+
+ void GenerateLoadGlobalIC(TypeofMode typeof_mode);
+ void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
+
+ void GenerateKeyedStoreIC(LanguageMode language_mode);
+ void GenerateKeyedStoreICTrampoline(LanguageMode language_mode);
+
+ void TryProbeStubCache(StubCache* stub_cache, Node* receiver, Node* name,
+ Label* if_handler, Variable* var_handler,
+ Label* if_miss);
+
+ Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) {
+ return StubCachePrimaryOffset(name, map);
+ }
+ Node* StubCacheSecondaryOffsetForTesting(Node* name, Node* map) {
+ return StubCacheSecondaryOffset(name, map);
+ }
+
+ struct LoadICParameters {
+ LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot,
+ Node* vector)
+ : context(context),
+ receiver(receiver),
+ name(name),
+ slot(slot),
+ vector(vector) {}
+
+ Node* context;
+ Node* receiver;
+ Node* name;
+ Node* slot;
+ 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)
+ : LoadICParameters(context, receiver, name, slot, vector),
+ value(value) {}
+ Node* value;
+ };
+
+ enum ElementSupport { kOnlyProperties, kSupportElements };
+ void HandleStoreICHandlerCase(
+ const StoreICParameters* p, Node* handler, Label* miss,
+ ElementSupport support_elements = kOnlyProperties);
+
+ private:
+ // Stub generation entry points.
+
+ void LoadIC(const LoadICParameters* p);
+ void LoadICProtoArray(const LoadICParameters* p, Node* handler,
+ bool throw_reference_error_if_nonexistent);
+ void LoadGlobalIC(const LoadICParameters* p, TypeofMode typeof_mode);
+ void KeyedLoadIC(const LoadICParameters* p);
+ void KeyedLoadICGeneric(const LoadICParameters* p);
+ void StoreIC(const StoreICParameters* p);
+ void KeyedStoreIC(const StoreICParameters* p, LanguageMode language_mode);
+
+ // IC dispatcher behavior.
+
+ // Checks monomorphic case. Returns {feedback} entry of the vector.
+ Node* TryMonomorphicCase(Node* slot, Node* vector, Node* receiver_map,
+ Label* if_handler, Variable* var_handler,
+ Label* if_miss);
+ void HandlePolymorphicCase(Node* receiver_map, Node* feedback,
+ Label* if_handler, Variable* var_handler,
+ Label* if_miss, int unroll_count);
+ void HandleKeyedStorePolymorphicCase(Node* receiver_map, Node* feedback,
+ Label* if_handler, Variable* var_handler,
+ Label* if_transition_handler,
+ Variable* var_transition_map_cell,
+ Label* if_miss);
+
+ // LoadIC implementation.
+
+ void HandleLoadICHandlerCase(
+ const LoadICParameters* p, Node* handler, Label* miss,
+ ElementSupport support_elements = kOnlyProperties);
+
+ 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,
+ Node* handler_length, Node* handler_flags,
+ Label* miss,
+ bool throw_reference_error_if_nonexistent);
+
+ // LoadGlobalIC implementation.
+
+ void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler,
+ Label* miss, ExitPoint* exit_point,
+ bool throw_reference_error_if_nonexistent);
+
+ // StoreIC implementation.
+
+ void HandleStoreICElementHandlerCase(const StoreICParameters* p,
+ Node* handler, Label* miss);
+
+ void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler,
+ Label* miss);
+ // If |transition| is nullptr then the normal field store is generated or
+ // transitioning store otherwise.
+ void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
+ Node* value, Node* transition, Label* miss);
+ // If |transition| is nullptr then the normal field store is generated or
+ // transitioning store otherwise.
+ void HandleStoreFieldAndReturn(Node* handler_word, Node* holder,
+ Representation representation, Node* value,
+ Node* transition, Label* miss);
+
+ // KeyedLoadIC_Generic implementation.
+
+ void GenericElementLoad(Node* receiver, Node* receiver_map,
+ Node* instance_type, Node* index, Label* slow);
+
+ void GenericPropertyLoad(Node* receiver, Node* receiver_map,
+ Node* instance_type, Node* key,
+ const LoadICParameters* p, Label* slow);
+
+ // Low-level helpers.
+
+ Node* PrepareValueForStore(Node* handler_word, Node* holder,
+ Representation representation, Node* transition,
+ Node* value, Label* bailout);
+
+ // Extends properties backing store by JSObject::kFieldsAdded elements.
+ void ExtendPropertiesBackingStore(Node* object);
+
+ void StoreNamedField(Node* handler_word, Node* object, bool is_inobject,
+ Representation representation, Node* value,
+ bool transition_to_field, Label* bailout);
+
+ void EmitFastElementsBoundsCheck(Node* object, Node* elements,
+ Node* intptr_index,
+ Node* is_jsarray_condition, Label* miss);
+ void EmitElementLoad(Node* object, Node* elements, Node* elements_kind,
+ 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, ExitPoint* exit_point);
+ void CheckPrototype(Node* prototype_cell, Node* name, Label* miss);
+ void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss);
+
+ // Stub cache access helpers.
+
+ // This enum is used here as a replacement for StubCache::Table to avoid
+ // including stub cache header.
+ enum StubCacheTable : int;
+
+ Node* StubCachePrimaryOffset(Node* name, Node* map);
+ Node* StubCacheSecondaryOffset(Node* name, Node* seed);
+
+ void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
+ Node* entry_offset, Node* name, Node* map,
+ Label* if_handler, Variable* var_handler,
+ 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
+
+#endif // V8_SRC_IC_ACCESSOR_ASSEMBLER_H_