| Index: src/compiler/js-type-feedback.cc
|
| diff --git a/src/compiler/js-type-feedback.cc b/src/compiler/js-type-feedback.cc
|
| index c82972a92f0a555e737922b2ff99b2f9855a90f1..689e4aca58e2e6be22026ff820295b2527c76a46 100644
|
| --- a/src/compiler/js-type-feedback.cc
|
| +++ b/src/compiler/js-type-feedback.cc
|
| @@ -25,13 +25,24 @@ namespace compiler {
|
|
|
| enum LoadOrStore { LOAD, STORE };
|
|
|
| +// TODO(turbofan): fix deoptimization problems
|
| +#define ENABLE_FAST_PROPERTY_LOADS false
|
| +#define ENABLE_FAST_PROPERTY_STORES false
|
| +
|
| JSTypeFeedbackTable::JSTypeFeedbackTable(Zone* zone)
|
| - : map_(TypeFeedbackIdMap::key_compare(),
|
| - TypeFeedbackIdMap::allocator_type(zone)) {}
|
| + : type_feedback_id_map_(TypeFeedbackIdMap::key_compare(),
|
| + TypeFeedbackIdMap::allocator_type(zone)),
|
| + feedback_vector_ic_slot_map_(TypeFeedbackIdMap::key_compare(),
|
| + TypeFeedbackIdMap::allocator_type(zone)) {}
|
|
|
|
|
| void JSTypeFeedbackTable::Record(Node* node, TypeFeedbackId id) {
|
| - map_.insert(std::make_pair(node->id(), id));
|
| + type_feedback_id_map_.insert(std::make_pair(node->id(), id));
|
| +}
|
| +
|
| +
|
| +void JSTypeFeedbackTable::Record(Node* node, FeedbackVectorICSlot slot) {
|
| + feedback_vector_ic_slot_map_.insert(std::make_pair(node->id(), slot));
|
| }
|
|
|
|
|
| @@ -136,6 +147,10 @@ static bool GetInObjectFieldAccess(LoadOrStore mode, Handle<Map> map,
|
| FieldIndex field_index = FieldIndex::ForPropertyIndex(*map, index, is_double);
|
|
|
| if (field_index.is_inobject()) {
|
| + if (is_double && !map->IsUnboxedDoubleField(field_index)) {
|
| + // TODO(turbofan): support for out-of-line (MutableHeapNumber) loads.
|
| + return false;
|
| + }
|
| access->offset = field_index.offset();
|
| return true;
|
| }
|
| @@ -162,19 +177,29 @@ Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) {
|
| Node* frame_state_before = GetFrameStateBefore(node);
|
| if (frame_state_before == nullptr) return NoChange();
|
|
|
| - // TODO(turbofan): handle vector-based type feedback.
|
| - TypeFeedbackId id = js_type_feedback_->find(node);
|
| - if (id.IsNone() || oracle()->LoadInlineCacheState(id) == UNINITIALIZED) {
|
| + const LoadNamedParameters& p = LoadNamedParametersOf(node->op());
|
| + Handle<Name> name = p.name().handle();
|
| + SmallMapList maps;
|
| +
|
| + FeedbackVectorICSlot slot = js_type_feedback_->FindFeedbackVectorICSlot(node);
|
| + if (slot.IsInvalid() ||
|
| + oracle()->LoadInlineCacheState(slot) == UNINITIALIZED) {
|
| + // No type feedback ids or the load is uninitialized.
|
| return NoChange();
|
| }
|
| + if (p.load_ic() == NAMED) {
|
| + oracle()->PropertyReceiverTypes(slot, name, &maps);
|
| + } else {
|
| + // The load named was originally a load property.
|
| + bool is_string; // Unused.
|
| + IcCheckType key_type; // Unused.
|
| + oracle()->KeyedPropertyReceiverTypes(slot, &maps, &is_string, &key_type);
|
| + }
|
|
|
| - const LoadNamedParameters& p = LoadNamedParametersOf(node->op());
|
| - SmallMapList maps;
|
| - Handle<Name> name = p.name().handle();
|
| Node* effect = NodeProperties::GetEffectInput(node);
|
| - GatherReceiverTypes(receiver, effect, id, name, &maps);
|
|
|
| if (maps.length() != 1) return NoChange(); // TODO(turbofan): polymorphism
|
| + if (!ENABLE_FAST_PROPERTY_LOADS) return NoChange();
|
|
|
| Handle<Map> map = maps.first();
|
| FieldAccess field_access;
|
| @@ -276,22 +301,35 @@ Reduction JSTypeFeedbackSpecializer::ReduceJSLoadProperty(Node* node) {
|
|
|
| Reduction JSTypeFeedbackSpecializer::ReduceJSStoreNamed(Node* node) {
|
| DCHECK(node->opcode() == IrOpcode::kJSStoreNamed);
|
| - if (true) return NoChange(); // TODO(titzer): storenamed is broken
|
| Node* frame_state_before = GetFrameStateBefore(node);
|
| if (frame_state_before == nullptr) return NoChange();
|
|
|
| - TypeFeedbackId id = js_type_feedback_->find(node);
|
| - if (id.IsNone() || oracle()->StoreIsUninitialized(id)) return NoChange();
|
| -
|
| const StoreNamedParameters& p = StoreNamedParametersOf(node->op());
|
| - SmallMapList maps;
|
| Handle<Name> name = p.name().handle();
|
| + SmallMapList maps;
|
| + TypeFeedbackId id = js_type_feedback_->FindTypeFeedbackId(node);
|
| + if (id.IsNone() || oracle()->StoreIsUninitialized(id) == UNINITIALIZED) {
|
| + // No type feedback ids or the store is uninitialized.
|
| + // TODO(titzer): no feedback from vector ICs from stores.
|
| + return NoChange();
|
| + } else {
|
| + if (p.store_ic() == NAMED) {
|
| + oracle()->PropertyReceiverTypes(id, name, &maps);
|
| + } else {
|
| + // The named store was originally a store property.
|
| + bool is_string; // Unused.
|
| + IcCheckType key_type; // Unused.
|
| + oracle()->KeyedPropertyReceiverTypes(id, &maps, &is_string, &key_type);
|
| + }
|
| + }
|
| +
|
| Node* receiver = node->InputAt(0);
|
| Node* effect = NodeProperties::GetEffectInput(node);
|
| - GatherReceiverTypes(receiver, effect, id, name, &maps);
|
|
|
| if (maps.length() != 1) return NoChange(); // TODO(turbofan): polymorphism
|
|
|
| + if (!ENABLE_FAST_PROPERTY_STORES) return NoChange();
|
| +
|
| Handle<Map> map = maps.first();
|
| FieldAccess field_access;
|
| if (!GetInObjectFieldAccess(STORE, map, name, &field_access)) {
|
| @@ -353,18 +391,6 @@ void JSTypeFeedbackSpecializer::BuildMapCheck(Node* receiver, Handle<Map> map,
|
| }
|
|
|
|
|
| -void JSTypeFeedbackSpecializer::GatherReceiverTypes(Node* receiver,
|
| - Node* effect,
|
| - TypeFeedbackId id,
|
| - Handle<Name> name,
|
| - SmallMapList* maps) {
|
| - // TODO(turbofan): filter maps by initial receiver map if known
|
| - // TODO(turbofan): filter maps by native context (if specializing)
|
| - // TODO(turbofan): filter maps by effect chain
|
| - oracle()->PropertyReceiverTypes(id, name, maps);
|
| -}
|
| -
|
| -
|
| // Get the frame state before an operation if it exists and has a valid
|
| // bailout id.
|
| Node* JSTypeFeedbackSpecializer::GetFrameStateBefore(Node* node) {
|
|
|