diff options
Diffstat (limited to 'deps/v8/src/ic/accessor-assembler.cc')
-rw-r--r-- | deps/v8/src/ic/accessor-assembler.cc | 94 |
1 files changed, 54 insertions, 40 deletions
diff --git a/deps/v8/src/ic/accessor-assembler.cc b/deps/v8/src/ic/accessor-assembler.cc index eb3971c54f..6508169558 100644 --- a/deps/v8/src/ic/accessor-assembler.cc +++ b/deps/v8/src/ic/accessor-assembler.cc @@ -984,15 +984,7 @@ void AccessorAssembler::HandleStoreFieldAndReturn(Node* handler_word, BIND(&if_out_of_object); { if (transition_to_field) { - Label storage_extended(this); - GotoIfNot(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word), - &storage_extended); - Comment("[ Extend storage"); - ExtendPropertiesBackingStore(holder); - Comment("] Extend storage"); - Goto(&storage_extended); - - BIND(&storage_extended); + ExtendPropertiesBackingStore(holder, handler_word); } StoreNamedField(handler_word, holder, false, representation, prepared_value, @@ -1053,7 +1045,12 @@ Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder, return value; } -void AccessorAssembler::ExtendPropertiesBackingStore(Node* object) { +void AccessorAssembler::ExtendPropertiesBackingStore(Node* object, + Node* handler_word) { + Label done(this); + GotoIfNot(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word), &done); + Comment("[ Extend storage"); + ParameterMode mode = OptimalParameterMode(); Node* properties = LoadProperties(object); @@ -1061,6 +1058,14 @@ void AccessorAssembler::ExtendPropertiesBackingStore(Node* object) { ? LoadAndUntagFixedArrayBaseLength(properties) : LoadFixedArrayBaseLength(properties); + // Previous property deletion could have left behind unused backing store + // capacity even for a map that think it doesn't have any unused fields. + // Perform a bounds check to see if we actually have to grow the array. + Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word); + Node* size = ElementOffsetFromIndex(length, FAST_ELEMENTS, mode, + FixedArray::kHeaderSize); + GotoIf(UintPtrLessThan(offset, size), &done); + Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode); Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode); @@ -1088,6 +1093,10 @@ void AccessorAssembler::ExtendPropertiesBackingStore(Node* object) { SKIP_WRITE_BARRIER, mode); StoreObjectField(object, JSObject::kPropertiesOffset, new_properties); + Comment("] Extend storage"); + Goto(&done); + + BIND(&done); } void AccessorAssembler::StoreNamedField(Node* handler_word, Node* object, @@ -1512,7 +1521,10 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, &found_handler, &var_handler, &stub_cache_miss); BIND(&found_handler); - { HandleLoadICHandlerCase(p, var_handler.value(), slow, &direct_exit); } + { + HandleLoadICHandlerCase(p, var_handler.value(), &stub_cache_miss, + &direct_exit); + } BIND(&stub_cache_miss); { @@ -1865,33 +1877,19 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) { LoadRoot(Heap::kpremonomorphic_symbolRootIndex), SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS); - Label not_function_prototype(this); - GotoIf(Word32NotEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)), - ¬_function_prototype); - GotoIfNot(WordEqual(p->name, LoadRoot(Heap::kprototype_stringRootIndex)), - ¬_function_prototype); - Node* bit_field = LoadMapBitField(receiver_map); - GotoIf(IsSetWord32(bit_field, 1 << Map::kHasNonInstancePrototype), - ¬_function_prototype); - // Function.prototype load. - { - // TODO(jkummerow): Unify with LoadIC_FunctionPrototype builtin - // (when we have a shared CSA base class for all builtins). - Node* proto_or_map = - LoadObjectField(receiver, JSFunction::kPrototypeOrInitialMapOffset); - GotoIf(IsTheHole(proto_or_map), &miss); - - VARIABLE(var_result, MachineRepresentation::kTagged, proto_or_map); - Label done(this, &var_result); - GotoIfNot(IsMap(proto_or_map), &done); - - var_result.Bind(LoadMapPrototype(proto_or_map)); - Goto(&done); - - BIND(&done); - Return(var_result.value()); + { + // Special case for Function.prototype load, because it's very common + // for ICs that are only executed once (MyFunc.prototype.foo = ...). + Label not_function_prototype(this); + GotoIf(Word32NotEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)), + ¬_function_prototype); + GotoIfNot(IsPrototypeString(p->name), ¬_function_prototype); + Node* bit_field = LoadMapBitField(receiver_map); + GotoIf(IsSetWord32(bit_field, 1 << Map::kHasNonInstancePrototype), + ¬_function_prototype); + Return(LoadJSFunctionPrototype(receiver, &miss)); + BIND(¬_function_prototype); } - BIND(¬_function_prototype); GenericPropertyLoad(receiver, receiver_map, instance_type, p->name, p, &miss, kDontUseStubCache); @@ -2090,15 +2088,15 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { VARIABLE(var_index, MachineType::PointerRepresentation()); VARIABLE(var_unique, MachineRepresentation::kTagged); var_unique.Bind(p->name); // Dummy initialization. - Label if_index(this), if_unique_name(this), slow(this); + Label if_index(this), if_unique_name(this), if_notunique(this), slow(this); Node* receiver = p->receiver; GotoIf(TaggedIsSmi(receiver), &slow); Node* receiver_map = LoadMap(receiver); Node* instance_type = LoadMapInstanceType(receiver_map); - TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique, - &slow); + TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique, &slow, + &if_notunique); BIND(&if_index); { @@ -2112,6 +2110,22 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { var_unique.value(), p, &slow); } + BIND(&if_notunique); + { + if (FLAG_internalize_on_the_fly) { + Label not_in_string_table(this); + TryInternalizeString(p->name, &if_index, &var_index, &if_unique_name, + &var_unique, ¬_in_string_table, &slow); + + BIND(¬_in_string_table); + // If the string was not found in the string table, then no object can + // have a property with that name. + Return(UndefinedConstant()); + } else { + Goto(&slow); + } + } + BIND(&slow); { Comment("KeyedLoadGeneric_slow"); |