blob: 1699b5c855291db2840e7792b69138d2ac04a723 [file] [log] [blame]
// 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_IMPL_H_
#define V8_SRC_IC_ACCESSOR_ASSEMBLER_IMPL_H_
#include "src/code-stub-assembler.h"
namespace v8 {
namespace internal {
namespace compiler {
class CodeAssemblerState;
}
using compiler::Node;
#define ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(V) \
V(LoadIC) \
V(LoadField) \
V(LoadICTrampoline) \
V(KeyedLoadICTF) \
V(KeyedLoadICTrampolineTF) \
V(KeyedLoadICMegamorphic) \
V(StoreIC) \
V(StoreICTrampoline)
// The other IC entry points need custom handling because of additional
// parameters like "typeof_mode" or "language_mode".
class AccessorAssemblerImpl : public CodeStubAssembler {
public:
explicit AccessorAssemblerImpl(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
#define DECLARE_PUBLIC_METHOD(Name) void Generate##Name();
ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(DECLARE_PUBLIC_METHOD)
#undef DECLARE_PUBLIC_METHOD
void GenerateLoadICProtoArray(bool throw_reference_error_if_nonexistent);
void GenerateLoadGlobalIC(TypeofMode typeof_mode);
void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
void GenerateKeyedStoreICTF(LanguageMode language_mode);
void GenerateKeyedStoreICTrampolineTF(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);
}
protected:
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;
};
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,
ElementSupport support_elements);
void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler,
Variable* var_holder,
Variable* var_smi_handler,
Label* if_smi_handler, Label* miss,
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,
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);
// 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);
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);
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);
};
} // namespace internal
} // namespace v8
#endif // V8_SRC_IC_ACCESSOR_ASSEMBLER_IMPL_H_