[runtime] Ensure slow properties for simple {__proto__:null} literals.
With this CL we reduce the difference between directly using a null prototype in a literal or using Object.create(null). - The EmitFastCloneShallowObject builtin now supports cloning slow object boilerplates. - Unified behavior to find the matching Map and instantiating it for Object.create(null) and literals with a null prototype. - Cleanup of literal type parameter of CompileTimeValue, now in sync with ObjectLiteral flags. Review-Url: https://codereview.chromium.org/2445333002 Cr-Commit-Position: refs/heads/master@{#44941}
This commit is contained in:
parent
dc713be87d
commit
3f73fecb13
@ -490,7 +490,7 @@ void ObjectLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
|
||||
ObjectLiteral::Property* property = properties()->at(property_index);
|
||||
|
||||
Expression* value = property->value();
|
||||
if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
|
||||
if (!property->IsPrototype()) {
|
||||
if (FunctionLiteral::NeedsHomeObject(value)) {
|
||||
property->SetSlot(spec->AddStoreICSlot(language_mode));
|
||||
}
|
||||
@ -512,7 +512,7 @@ void ObjectLiteral::CalculateEmitStore(Zone* zone) {
|
||||
for (int i = properties()->length() - 1; i >= 0; i--) {
|
||||
ObjectLiteral::Property* property = properties()->at(i);
|
||||
if (property->is_computed_name()) continue;
|
||||
if (property->kind() == ObjectLiteral::Property::PROTOTYPE) continue;
|
||||
if (property->IsPrototype()) continue;
|
||||
Literal* literal = property->key()->AsLiteral();
|
||||
DCHECK(!literal->IsNullLiteral());
|
||||
|
||||
@ -532,31 +532,42 @@ void ObjectLiteral::CalculateEmitStore(Zone* zone) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
|
||||
return property != NULL &&
|
||||
property->kind() != ObjectLiteral::Property::PROTOTYPE;
|
||||
void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
|
||||
// We still check for __proto__:null after computed property names.
|
||||
for (; i < properties()->length(); i++) {
|
||||
if (properties()->at(i)->IsNullPrototype()) {
|
||||
set_has_null_protoype(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectLiteral::InitDepthAndFlags() {
|
||||
if (depth_ > 0) return;
|
||||
|
||||
int position = 0;
|
||||
// Accumulate the value in local variables and store it at the end.
|
||||
if (is_initialized()) return;
|
||||
bool is_simple = true;
|
||||
bool has_seen_prototype = false;
|
||||
int depth_acc = 1;
|
||||
uint32_t max_element_index = 0;
|
||||
uint32_t nof_properties = 0;
|
||||
uint32_t elements = 0;
|
||||
uint32_t max_element_index = 0;
|
||||
for (int i = 0; i < properties()->length(); i++) {
|
||||
ObjectLiteral::Property* property = properties()->at(i);
|
||||
if (!IsBoilerplateProperty(property)) {
|
||||
if (property->IsPrototype()) {
|
||||
has_seen_prototype = true;
|
||||
// __proto__:null has no side-effects and is set directly on the
|
||||
// boilerplate.
|
||||
if (property->IsNullPrototype()) {
|
||||
set_has_null_protoype(true);
|
||||
continue;
|
||||
}
|
||||
DCHECK(!has_null_prototype());
|
||||
is_simple = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
|
||||
if (nof_properties == boilerplate_properties_) {
|
||||
DCHECK(property->is_computed_name());
|
||||
is_simple = false;
|
||||
if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
|
||||
break;
|
||||
}
|
||||
DCHECK(!property->is_computed_name());
|
||||
@ -596,15 +607,12 @@ void ObjectLiteral::InitDepthAndFlags() {
|
||||
elements++;
|
||||
}
|
||||
|
||||
// Increment the position for the key and the value.
|
||||
position += 2;
|
||||
nof_properties++;
|
||||
}
|
||||
|
||||
bit_field_ = FastElementsField::update(
|
||||
bit_field_,
|
||||
(max_element_index <= 32) || ((2 * elements) >= max_element_index));
|
||||
bit_field_ = HasElementsField::update(bit_field_, elements > 0);
|
||||
|
||||
set_fast_elements((max_element_index <= 32) ||
|
||||
((2 * elements) >= max_element_index));
|
||||
set_has_elements(elements > 0);
|
||||
set_is_simple(is_simple);
|
||||
set_depth(depth_acc);
|
||||
}
|
||||
@ -616,7 +624,7 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
|
||||
bool has_seen_proto = false;
|
||||
for (int i = 0; i < properties()->length(); i++) {
|
||||
ObjectLiteral::Property* property = properties()->at(i);
|
||||
if (!IsBoilerplateProperty(property)) {
|
||||
if (property->IsPrototype()) {
|
||||
has_seen_proto = true;
|
||||
continue;
|
||||
}
|
||||
@ -641,9 +649,7 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
|
||||
int position = 0;
|
||||
for (int i = 0; i < properties()->length(); i++) {
|
||||
ObjectLiteral::Property* property = properties()->at(i);
|
||||
if (!IsBoilerplateProperty(property)) {
|
||||
continue;
|
||||
}
|
||||
if (property->IsPrototype()) continue;
|
||||
|
||||
if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
|
||||
DCHECK(property->is_computed_name());
|
||||
@ -693,7 +699,7 @@ ElementsKind ArrayLiteral::constant_elements_kind() const {
|
||||
void ArrayLiteral::InitDepthAndFlags() {
|
||||
DCHECK_LT(first_spread_index_, 0);
|
||||
|
||||
if (depth_ > 0) return;
|
||||
if (is_initialized()) return;
|
||||
|
||||
int constants_length = values()->length();
|
||||
|
||||
|
@ -1238,9 +1238,9 @@ class Literal final : public Expression {
|
||||
// Base class for literals that need space in the type feedback vector.
|
||||
class MaterializedLiteral : public Expression {
|
||||
public:
|
||||
bool is_initialized() const { return 0 < depth_; }
|
||||
int depth() const {
|
||||
// only callable after initialization.
|
||||
DCHECK(depth_ >= 1);
|
||||
DCHECK(is_initialized());
|
||||
return depth_;
|
||||
}
|
||||
|
||||
@ -1270,10 +1270,11 @@ class MaterializedLiteral : public Expression {
|
||||
void set_is_simple(bool is_simple) {
|
||||
bit_field_ = IsSimpleField::update(bit_field_, is_simple);
|
||||
}
|
||||
|
||||
friend class CompileTimeValue;
|
||||
|
||||
void set_depth(int depth) {
|
||||
DCHECK_LE(1, depth);
|
||||
DCHECK(!is_initialized());
|
||||
depth_ = depth;
|
||||
}
|
||||
|
||||
@ -1359,6 +1360,11 @@ class ObjectLiteralProperty final : public LiteralProperty {
|
||||
|
||||
void set_receiver_type(Handle<Map> map) { receiver_type_ = map; }
|
||||
|
||||
bool IsNullPrototype() const {
|
||||
return IsPrototype() && value()->IsNullLiteral();
|
||||
}
|
||||
bool IsPrototype() const { return kind() == PROTOTYPE; }
|
||||
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
@ -1396,9 +1402,9 @@ class ObjectLiteral final : public MaterializedLiteral {
|
||||
bool has_rest_property() const {
|
||||
return HasRestPropertyField::decode(bit_field_);
|
||||
}
|
||||
|
||||
// Decide if a property should be in the object boilerplate.
|
||||
static bool IsBoilerplateProperty(Property* property);
|
||||
bool has_null_prototype() const {
|
||||
return HasNullPrototypeField::decode(bit_field_);
|
||||
}
|
||||
|
||||
// Populate the depth field and flags.
|
||||
void InitDepthAndFlags();
|
||||
@ -1426,12 +1432,16 @@ class ObjectLiteral final : public MaterializedLiteral {
|
||||
// Assemble bitfield of flags for the CreateObjectLiteral helper.
|
||||
int ComputeFlags(bool disable_mementos = false) const {
|
||||
int flags = fast_elements() ? kFastElements : kNoFlags;
|
||||
if (has_shallow_properties()) {
|
||||
flags |= kShallowProperties;
|
||||
}
|
||||
if (disable_mementos) {
|
||||
flags |= kDisableMementos;
|
||||
}
|
||||
if (has_shallow_properties()) flags |= kShallowProperties;
|
||||
if (disable_mementos) flags |= kDisableMementos;
|
||||
if (has_null_prototype()) flags |= kHasNullPrototype;
|
||||
return flags;
|
||||
}
|
||||
|
||||
int EncodeLiteralType() {
|
||||
int flags = fast_elements() ? kFastElements : kNoFlags;
|
||||
if (has_shallow_properties()) flags |= kShallowProperties;
|
||||
if (has_null_prototype()) flags |= kHasNullPrototype;
|
||||
return flags;
|
||||
}
|
||||
|
||||
@ -1440,7 +1450,7 @@ class ObjectLiteral final : public MaterializedLiteral {
|
||||
kFastElements = 1,
|
||||
kShallowProperties = 1 << 1,
|
||||
kDisableMementos = 1 << 2,
|
||||
kHasRestProperty = 1 << 3,
|
||||
kHasNullPrototype = 1 << 3,
|
||||
};
|
||||
|
||||
struct Accessors: public ZoneObject {
|
||||
@ -1476,12 +1486,25 @@ class ObjectLiteral final : public MaterializedLiteral {
|
||||
bit_field_ |= FastElementsField::encode(false) |
|
||||
HasElementsField::encode(false) |
|
||||
MayStoreDoublesField::encode(false) |
|
||||
HasRestPropertyField::encode(has_rest_property);
|
||||
HasRestPropertyField::encode(has_rest_property) |
|
||||
HasNullPrototypeField::encode(false);
|
||||
}
|
||||
|
||||
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
|
||||
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
|
||||
|
||||
void InitFlagsForPendingNullPrototype(int i);
|
||||
|
||||
void set_fast_elements(bool fast_elements) {
|
||||
bit_field_ = FastElementsField::update(bit_field_, fast_elements);
|
||||
}
|
||||
void set_has_elements(bool has_elements) {
|
||||
bit_field_ = HasElementsField::update(bit_field_, has_elements);
|
||||
}
|
||||
void set_has_null_protoype(bool has_null_prototype) {
|
||||
bit_field_ = HasNullPrototypeField::update(bit_field_, has_null_prototype);
|
||||
}
|
||||
|
||||
uint32_t boilerplate_properties_;
|
||||
Handle<BoilerplateDescription> constant_properties_;
|
||||
ZoneList<Property*>* properties_;
|
||||
@ -1494,6 +1517,8 @@ class ObjectLiteral final : public MaterializedLiteral {
|
||||
: public BitField<bool, HasElementsField::kNext, 1> {};
|
||||
class HasRestPropertyField
|
||||
: public BitField<bool, MayStoreDoublesField::kNext, 1> {};
|
||||
class HasNullPrototypeField
|
||||
: public BitField<bool, HasRestPropertyField::kNext, 1> {};
|
||||
};
|
||||
|
||||
|
||||
@ -1582,9 +1607,7 @@ class ArrayLiteral final : public MaterializedLiteral {
|
||||
// Assemble bitfield of flags for the CreateArrayLiteral helper.
|
||||
int ComputeFlags(bool disable_mementos = false) const {
|
||||
int flags = depth() == 1 ? kShallowElements : kNoFlags;
|
||||
if (disable_mementos) {
|
||||
flags |= kDisableMementos;
|
||||
}
|
||||
if (disable_mementos) flags |= kDisableMementos;
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
@ -24,28 +24,24 @@ Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
|
||||
Factory* factory = isolate->factory();
|
||||
DCHECK(IsCompileTimeValue(expression));
|
||||
Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
|
||||
ObjectLiteral* object_literal = expression->AsObjectLiteral();
|
||||
if (object_literal != NULL) {
|
||||
if (expression->IsObjectLiteral()) {
|
||||
ObjectLiteral* object_literal = expression->AsObjectLiteral();
|
||||
DCHECK(object_literal->is_simple());
|
||||
if (object_literal->fast_elements()) {
|
||||
result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
|
||||
} else {
|
||||
result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
|
||||
}
|
||||
int literalTypeFlag = object_literal->EncodeLiteralType();
|
||||
DCHECK_NE(kArrayLiteralFlag, literalTypeFlag);
|
||||
result->set(kLiteralTypeSlot, Smi::FromInt(literalTypeFlag));
|
||||
result->set(kElementsSlot, *object_literal->constant_properties());
|
||||
} else {
|
||||
ArrayLiteral* array_literal = expression->AsArrayLiteral();
|
||||
DCHECK(array_literal != NULL && array_literal->is_simple());
|
||||
result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
|
||||
result->set(kLiteralTypeSlot, Smi::FromInt(kArrayLiteralFlag));
|
||||
result->set(kElementsSlot, *array_literal->constant_elements());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
|
||||
Handle<FixedArray> value) {
|
||||
Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
|
||||
return static_cast<LiteralType>(literal_type->value());
|
||||
int CompileTimeValue::GetLiteralTypeFlags(Handle<FixedArray> value) {
|
||||
return Smi::cast(value->get(kLiteralTypeSlot))->value();
|
||||
}
|
||||
|
||||
Handle<HeapObject> CompileTimeValue::GetElements(Handle<FixedArray> value) {
|
||||
|
@ -17,19 +17,20 @@ class Expression;
|
||||
// can be fully handled at compile time.
|
||||
class CompileTimeValue : public AllStatic {
|
||||
public:
|
||||
enum LiteralType {
|
||||
OBJECT_LITERAL_FAST_ELEMENTS,
|
||||
OBJECT_LITERAL_SLOW_ELEMENTS,
|
||||
ARRAY_LITERAL
|
||||
};
|
||||
// This is a special marker used to encode array literals. The value has to be
|
||||
// different from any value possibly returned by
|
||||
// ObjectLiteral::EncodeLiteralType.
|
||||
static const int kArrayLiteralFlag = -1;
|
||||
|
||||
static bool IsCompileTimeValue(Expression* expression);
|
||||
|
||||
// Get the value as a compile time value.
|
||||
static Handle<FixedArray> GetValue(Isolate* isolate, Expression* expression);
|
||||
|
||||
// Get the type of a compile time value returned by GetValue().
|
||||
static LiteralType GetLiteralType(Handle<FixedArray> value);
|
||||
// Get the encoded literal type. This can either be kArrayLiteralFlag or
|
||||
// encoded properties of an ObjectLiteral returned by
|
||||
// ObjectLiteral::EncodeLiteralType.
|
||||
static int GetLiteralTypeFlags(Handle<FixedArray> value);
|
||||
|
||||
// Get the elements of a compile time value returned by GetValue().
|
||||
static Handle<HeapObject> GetElements(Handle<FixedArray> value);
|
||||
|
@ -569,6 +569,20 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
|
||||
|
||||
native_context()->set_initial_object_prototype(*object_function_prototype);
|
||||
JSFunction::SetPrototype(object_fun, object_function_prototype);
|
||||
|
||||
{
|
||||
// Set up slow map for Object.create(null) instances without in-object
|
||||
// properties.
|
||||
Handle<Map> map(object_fun->initial_map(), isolate);
|
||||
map = Map::CopyInitialMapNormalized(map);
|
||||
Map::SetPrototype(map, isolate->factory()->null_value());
|
||||
native_context()->set_slow_object_with_null_prototype_map(*map);
|
||||
|
||||
// Set up slow map for literals with too many properties.
|
||||
map = Map::Copy(map, "slow_object_with_object_prototype_map");
|
||||
Map::SetPrototype(map, object_function_prototype);
|
||||
native_context()->set_slow_object_with_object_prototype_map(*map);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the empty function as the prototype for function - ES6 19.2.3
|
||||
@ -4247,20 +4261,13 @@ bool Genesis::InstallNatives(GlobalContextType context_type) {
|
||||
|
||||
// Store the map for the %ObjectPrototype% after the natives has been compiled
|
||||
// and the Object function has been set up.
|
||||
Handle<JSFunction> object_function(native_context()->object_function());
|
||||
DCHECK(JSObject::cast(object_function->initial_map()->prototype())
|
||||
->HasFastProperties());
|
||||
native_context()->set_object_function_prototype_map(
|
||||
HeapObject::cast(object_function->initial_map()->prototype())->map());
|
||||
|
||||
// Set up the map for Object.create(null) instances.
|
||||
Handle<Map> slow_object_with_null_prototype_map =
|
||||
Map::CopyInitialMap(handle(object_function->initial_map(), isolate()));
|
||||
slow_object_with_null_prototype_map->set_dictionary_map(true);
|
||||
Map::SetPrototype(slow_object_with_null_prototype_map,
|
||||
isolate()->factory()->null_value());
|
||||
native_context()->set_slow_object_with_null_prototype_map(
|
||||
*slow_object_with_null_prototype_map);
|
||||
{
|
||||
Handle<JSFunction> object_function(native_context()->object_function());
|
||||
DCHECK(JSObject::cast(object_function->initial_map()->prototype())
|
||||
->HasFastProperties());
|
||||
native_context()->set_object_function_prototype_map(
|
||||
HeapObject::cast(object_function->initial_map()->prototype())->map());
|
||||
}
|
||||
|
||||
// Store the map for the %StringPrototype% after the natives has been compiled
|
||||
// and the String function has been set up.
|
||||
|
@ -617,30 +617,48 @@ TF_BUILTIN(FastCloneShallowArrayDontTrack, ConstructorBuiltinsAssembler) {
|
||||
|
||||
Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowObject(
|
||||
Label* call_runtime, Node* closure, Node* literals_index,
|
||||
Node* properties_count) {
|
||||
Node* fast_properties_count) {
|
||||
Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
|
||||
Node* feedback_vector = LoadObjectField(cell, Cell::kValueOffset);
|
||||
Node* allocation_site = LoadFixedArrayElement(
|
||||
feedback_vector, literals_index, 0, CodeStubAssembler::SMI_PARAMETERS);
|
||||
GotoIf(IsUndefined(allocation_site), call_runtime);
|
||||
|
||||
Node* boilerplate =
|
||||
LoadObjectField(allocation_site, AllocationSite::kTransitionInfoOffset);
|
||||
Node* boilerplate_map = LoadMap(boilerplate);
|
||||
Variable properties(this, MachineRepresentation::kTagged,
|
||||
EmptyFixedArrayConstant());
|
||||
// TODO(cbruni): directly use the property count from the boilerplate map.
|
||||
Variable in_object_property_count(this, MachineType::PointerRepresentation(),
|
||||
fast_properties_count);
|
||||
// Directly copy over the property store for dict-mode boilerplates.
|
||||
Label dict_properties(this), allocate_object(this);
|
||||
Branch(IsDictionaryMap(boilerplate_map), &dict_properties, &allocate_object);
|
||||
Bind(&dict_properties);
|
||||
{
|
||||
properties.Bind(
|
||||
CopyNameDictionary(LoadProperties(boilerplate), call_runtime));
|
||||
in_object_property_count.Bind(IntPtrConstant(0));
|
||||
Goto(&allocate_object);
|
||||
}
|
||||
Bind(&allocate_object);
|
||||
|
||||
// Calculate the object and allocation size based on the properties count.
|
||||
Node* object_size = IntPtrAdd(WordShl(properties_count, kPointerSizeLog2),
|
||||
IntPtrConstant(JSObject::kHeaderSize));
|
||||
Node* object_size =
|
||||
IntPtrAdd(WordShl(in_object_property_count.value(), kPointerSizeLog2),
|
||||
IntPtrConstant(JSObject::kHeaderSize));
|
||||
Node* allocation_size = object_size;
|
||||
if (FLAG_allocation_site_pretenuring) {
|
||||
allocation_size =
|
||||
IntPtrAdd(object_size, IntPtrConstant(AllocationMemento::kSize));
|
||||
}
|
||||
Node* boilerplate =
|
||||
LoadObjectField(allocation_site, AllocationSite::kTransitionInfoOffset);
|
||||
Node* boilerplate_map = LoadMap(boilerplate);
|
||||
|
||||
Node* instance_size = LoadMapInstanceSize(boilerplate_map);
|
||||
Node* size_in_words = WordShr(object_size, kPointerSizeLog2);
|
||||
GotoIfNot(WordEqual(instance_size, size_in_words), call_runtime);
|
||||
|
||||
Node* copy = AllocateInNewSpace(allocation_size);
|
||||
|
||||
// Copy boilerplate elements.
|
||||
VARIABLE(offset, MachineType::PointerRepresentation());
|
||||
offset.Bind(IntPtrConstant(-kHeapObjectTag));
|
||||
@ -664,6 +682,9 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowObject(
|
||||
GotoIfNot(IntPtrGreaterThanOrEqual(offset.value(), end_offset), &loop_body);
|
||||
}
|
||||
|
||||
StoreObjectFieldNoWriteBarrier(copy, JSObject::kPropertiesOffset,
|
||||
properties.value());
|
||||
|
||||
if (FLAG_allocation_site_pretenuring) {
|
||||
Node* memento = InnerAllocate(copy, object_size);
|
||||
StoreMapNoWriteBarrier(memento, Heap::kAllocationMementoMapRootIndex);
|
||||
|
@ -2047,6 +2047,21 @@ Node* CodeStubAssembler::AllocateNameDictionary(Node* at_least_space_for) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::CopyNameDictionary(Node* dictionary,
|
||||
Label* large_object_fallback) {
|
||||
Comment("Copy boilerplate property dict");
|
||||
Label done(this);
|
||||
Node* length = SmiUntag(LoadFixedArrayBaseLength(dictionary));
|
||||
GotoIf(
|
||||
IntPtrGreaterThan(length, IntPtrConstant(FixedArray::kMaxRegularLength)),
|
||||
large_object_fallback);
|
||||
Node* properties =
|
||||
AllocateNameDictionary(SmiUntag(GetCapacity<NameDictionary>(dictionary)));
|
||||
CopyFixedArrayElements(FAST_ELEMENTS, dictionary, properties, length,
|
||||
SKIP_WRITE_BARRIER, INTPTR_PARAMETERS);
|
||||
return properties;
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::AllocateJSObjectFromMap(Node* map, Node* properties,
|
||||
Node* elements,
|
||||
AllocationFlags flags) {
|
||||
|
@ -569,6 +569,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
|
||||
Node* AllocateNameDictionary(int capacity);
|
||||
Node* AllocateNameDictionary(Node* capacity);
|
||||
Node* CopyNameDictionary(Node* dictionary, Label* large_object_fallback);
|
||||
|
||||
Node* AllocateJSObjectFromMap(Node* map, Node* properties = nullptr,
|
||||
Node* elements = nullptr,
|
||||
|
@ -343,6 +343,8 @@ enum ContextLookupFlags {
|
||||
V(SLOW_ALIASED_ARGUMENTS_MAP_INDEX, Map, slow_aliased_arguments_map) \
|
||||
V(SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP, Map, \
|
||||
slow_object_with_null_prototype_map) \
|
||||
V(SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP, Map, \
|
||||
slow_object_with_object_prototype_map) \
|
||||
V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_INDEX, UnseededNumberDictionary, \
|
||||
slow_template_instantiations_cache) \
|
||||
V(STRICT_ARGUMENTS_MAP_INDEX, Map, strict_arguments_map) \
|
||||
|
@ -1863,6 +1863,15 @@ Handle<JSObject> Factory::NewJSObjectFromMap(
|
||||
JSObject);
|
||||
}
|
||||
|
||||
Handle<JSObject> Factory::NewSlowJSObjectFromMap(Handle<Map> map, int capacity,
|
||||
PretenureFlag pretenure) {
|
||||
DCHECK(map->is_dictionary_map());
|
||||
Handle<FixedArray> object_properties =
|
||||
NameDictionary::New(isolate(), capacity);
|
||||
Handle<JSObject> js_object = NewJSObjectFromMap(map, pretenure);
|
||||
js_object->set_properties(*object_properties);
|
||||
return js_object;
|
||||
}
|
||||
|
||||
Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind,
|
||||
PretenureFlag pretenure) {
|
||||
@ -2663,32 +2672,31 @@ Handle<JSWeakMap> Factory::NewJSWeakMap() {
|
||||
return Handle<JSWeakMap>::cast(NewJSObjectFromMap(map));
|
||||
}
|
||||
|
||||
|
||||
Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
|
||||
int number_of_properties,
|
||||
bool* is_result_from_cache) {
|
||||
Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> native_context,
|
||||
int number_of_properties) {
|
||||
DCHECK(native_context->IsNativeContext());
|
||||
const int kMapCacheSize = 128;
|
||||
|
||||
// We do not cache maps for too many properties or when running builtin code.
|
||||
if (number_of_properties > kMapCacheSize ||
|
||||
isolate()->bootstrapper()->IsActive()) {
|
||||
*is_result_from_cache = false;
|
||||
Handle<Map> map = Map::Create(isolate(), number_of_properties);
|
||||
return map;
|
||||
if (isolate()->bootstrapper()->IsActive()) {
|
||||
return Map::Create(isolate(), number_of_properties);
|
||||
}
|
||||
// Use initial slow object proto map for too many properties.
|
||||
if (number_of_properties > kMapCacheSize) {
|
||||
return handle(native_context->slow_object_with_object_prototype_map(),
|
||||
isolate());
|
||||
}
|
||||
*is_result_from_cache = true;
|
||||
if (number_of_properties == 0) {
|
||||
// Reuse the initial map of the Object function if the literal has no
|
||||
// predeclared properties.
|
||||
return handle(context->object_function()->initial_map(), isolate());
|
||||
return handle(native_context->object_function()->initial_map(), isolate());
|
||||
}
|
||||
|
||||
int cache_index = number_of_properties - 1;
|
||||
Handle<Object> maybe_cache(context->map_cache(), isolate());
|
||||
Handle<Object> maybe_cache(native_context->map_cache(), isolate());
|
||||
if (maybe_cache->IsUndefined(isolate())) {
|
||||
// Allocate the new map cache for the native context.
|
||||
maybe_cache = NewFixedArray(kMapCacheSize, TENURED);
|
||||
context->set_map_cache(*maybe_cache);
|
||||
native_context->set_map_cache(*maybe_cache);
|
||||
} else {
|
||||
// Check to see whether there is a matching element in the cache.
|
||||
Handle<FixedArray> cache = Handle<FixedArray>::cast(maybe_cache);
|
||||
@ -2696,13 +2704,16 @@ Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
|
||||
if (result->IsWeakCell()) {
|
||||
WeakCell* cell = WeakCell::cast(result);
|
||||
if (!cell->cleared()) {
|
||||
return handle(Map::cast(cell->value()), isolate());
|
||||
Map* map = Map::cast(cell->value());
|
||||
DCHECK(!map->is_dictionary_map());
|
||||
return handle(map, isolate());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create a new map and add it to the cache.
|
||||
Handle<FixedArray> cache = Handle<FixedArray>::cast(maybe_cache);
|
||||
Handle<Map> map = Map::Create(isolate(), number_of_properties);
|
||||
DCHECK(!map->is_dictionary_map());
|
||||
Handle<WeakCell> cell = NewWeakCell(map);
|
||||
cache->set(cache_index, *cell);
|
||||
return map;
|
||||
|
@ -478,6 +478,10 @@ class V8_EXPORT_PRIVATE Factory final {
|
||||
Handle<Map> map,
|
||||
PretenureFlag pretenure = NOT_TENURED,
|
||||
Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
|
||||
Handle<JSObject> NewSlowJSObjectFromMap(
|
||||
Handle<Map> map,
|
||||
int number_of_slow_properties = NameDictionary::kInitialCapacity,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
// JS arrays are pretenured when allocated by the parser.
|
||||
|
||||
@ -769,9 +773,8 @@ class V8_EXPORT_PRIVATE Factory final {
|
||||
|
||||
// Return a map for given number of properties using the map cache in the
|
||||
// native context.
|
||||
Handle<Map> ObjectLiteralMapFromCache(Handle<Context> context,
|
||||
int number_of_properties,
|
||||
bool* is_result_from_cache);
|
||||
Handle<Map> ObjectLiteralMapFromCache(Handle<Context> native_context,
|
||||
int number_of_properties);
|
||||
|
||||
Handle<RegExpMatchInfo> NewRegExpMatchInfo();
|
||||
|
||||
|
@ -18,7 +18,7 @@ namespace interpreter {
|
||||
|
||||
class CreateArrayLiteralFlags {
|
||||
public:
|
||||
class FlagsBits : public BitField8<int, 0, 3> {};
|
||||
class FlagsBits : public BitField8<int, 0, 4> {};
|
||||
class FastShallowCloneBit : public BitField8<bool, FlagsBits::kNext, 1> {};
|
||||
|
||||
static uint8_t Encode(bool use_fast_shallow_clone, int runtime_flags);
|
||||
@ -29,7 +29,7 @@ class CreateArrayLiteralFlags {
|
||||
|
||||
class CreateObjectLiteralFlags {
|
||||
public:
|
||||
class FlagsBits : public BitField8<int, 0, 3> {};
|
||||
class FlagsBits : public BitField8<int, 0, 4> {};
|
||||
class FastClonePropertiesCountBits
|
||||
: public BitField8<int, FlagsBits::kNext, 3> {};
|
||||
|
||||
|
@ -1756,6 +1756,8 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
break;
|
||||
}
|
||||
case ObjectLiteral::Property::PROTOTYPE: {
|
||||
// __proto__:null is handled by CreateObjectLiteral.
|
||||
if (property->IsNullPrototype()) break;
|
||||
DCHECK(property->emit_store());
|
||||
RegisterList args = register_allocator()->NewRegisterList(2);
|
||||
builder()->MoveRegister(literal, args[0]);
|
||||
@ -1805,7 +1807,9 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
||||
RegisterAllocationScope inner_register_scope(this);
|
||||
|
||||
if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
|
||||
if (property->IsPrototype()) {
|
||||
// __proto__:null is handled by CreateObjectLiteral.
|
||||
if (property->IsNullPrototype()) continue;
|
||||
DCHECK(property->emit_store());
|
||||
RegisterList args = register_allocator()->NewRegisterList(2);
|
||||
builder()->MoveRegister(literal, args[0]);
|
||||
|
@ -8707,9 +8707,8 @@ Handle<Map> Map::TransitionToImmutableProto(Handle<Map> map) {
|
||||
return new_map;
|
||||
}
|
||||
|
||||
Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
|
||||
int in_object_properties,
|
||||
int unused_property_fields) {
|
||||
namespace {
|
||||
void EnsureInitialMap(Handle<Map> map) {
|
||||
#ifdef DEBUG
|
||||
Isolate* isolate = map->GetIsolate();
|
||||
// Strict function maps have Function as a constructor but the
|
||||
@ -8727,7 +8726,21 @@ Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
|
||||
DCHECK(map->owns_descriptors());
|
||||
DCHECK_EQ(map->NumberOfOwnDescriptors(),
|
||||
map->instance_descriptors()->number_of_descriptors());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
Handle<Map> Map::CopyInitialMapNormalized(Handle<Map> map,
|
||||
PropertyNormalizationMode mode) {
|
||||
EnsureInitialMap(map);
|
||||
return CopyNormalized(map, mode);
|
||||
}
|
||||
|
||||
// static
|
||||
Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
|
||||
int in_object_properties,
|
||||
int unused_property_fields) {
|
||||
EnsureInitialMap(map);
|
||||
Handle<Map> result = RawCopy(map, instance_size);
|
||||
|
||||
// Please note instance_type and instance_size are set when allocated.
|
||||
|
@ -2834,6 +2834,10 @@ class FixedArray: public FixedArrayBase {
|
||||
static const int kMaxSize = 128 * MB * kPointerSize;
|
||||
// Maximally allowed length of a FixedArray.
|
||||
static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
|
||||
// Maximally allowed length for regular (non large object space) object.
|
||||
STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
|
||||
static const int kMaxRegularLength =
|
||||
(kMaxRegularHeapObjectSize - kHeaderSize) / kPointerSize;
|
||||
|
||||
// Dispatched behavior.
|
||||
DECLARE_PRINTER(FixedArray)
|
||||
@ -4835,6 +4839,9 @@ class Map: public HeapObject {
|
||||
static Handle<Map> CopyInitialMap(Handle<Map> map, int instance_size,
|
||||
int in_object_properties,
|
||||
int unused_property_fields);
|
||||
static Handle<Map> CopyInitialMapNormalized(
|
||||
Handle<Map> map,
|
||||
PropertyNormalizationMode mode = CLEAR_INOBJECT_PROPERTIES);
|
||||
static Handle<Map> CopyDropDescriptors(Handle<Map> map);
|
||||
static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
|
||||
Descriptor* descriptor,
|
||||
|
@ -4242,7 +4242,7 @@ void Parser::SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
|
||||
|
||||
// Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
|
||||
// of an object literal.
|
||||
if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
|
||||
if (property->IsPrototype()) return;
|
||||
|
||||
Expression* value = property->value();
|
||||
|
||||
|
@ -750,7 +750,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
|
||||
V8_INLINE static bool IsBoilerplateProperty(
|
||||
ObjectLiteral::Property* property) {
|
||||
return ObjectLiteral::IsBoilerplateProperty(property);
|
||||
return !property->IsPrototype();
|
||||
}
|
||||
|
||||
V8_INLINE bool IsNative(Expression* expr) const {
|
||||
|
@ -14,65 +14,56 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
static Handle<Map> ComputeObjectLiteralMap(
|
||||
Handle<Context> context,
|
||||
Handle<BoilerplateDescription> boilerplate_description,
|
||||
bool* is_result_from_cache) {
|
||||
int number_of_properties = boilerplate_description->backing_store_size();
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
return isolate->factory()->ObjectLiteralMapFromCache(
|
||||
context, number_of_properties, is_result_from_cache);
|
||||
}
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
|
||||
Isolate* isolate, Handle<FeedbackVector> vector,
|
||||
Handle<BoilerplateDescription> boilerplate_description);
|
||||
Handle<FixedArray> compile_time_value);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
|
||||
Isolate* isolate, Handle<FeedbackVector> vector,
|
||||
Handle<BoilerplateDescription> boilerplate_description,
|
||||
bool should_have_fast_elements) {
|
||||
Handle<Context> context = isolate->native_context();
|
||||
bool use_fast_elements, bool has_null_prototype) {
|
||||
Handle<Context> native_context = isolate->native_context();
|
||||
|
||||
// In case we have function literals, we want the object to be in
|
||||
// slow properties mode for now. We don't go in the map cache because
|
||||
// maps with constant functions can't be shared if the functions are
|
||||
// not the same (which is the common case).
|
||||
bool is_result_from_cache = false;
|
||||
Handle<Map> map = ComputeObjectLiteralMap(context, boilerplate_description,
|
||||
&is_result_from_cache);
|
||||
int number_of_properties = boilerplate_description->backing_store_size();
|
||||
|
||||
// Ignoring number_of_properties for force dictionary map with __proto__:null.
|
||||
Handle<Map> map =
|
||||
has_null_prototype
|
||||
? handle(native_context->slow_object_with_null_prototype_map(),
|
||||
isolate)
|
||||
: isolate->factory()->ObjectLiteralMapFromCache(native_context,
|
||||
number_of_properties);
|
||||
|
||||
PretenureFlag pretenure_flag =
|
||||
isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED;
|
||||
|
||||
Handle<JSObject> boilerplate =
|
||||
isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
|
||||
map->is_dictionary_map()
|
||||
? isolate->factory()->NewSlowJSObjectFromMap(
|
||||
map, number_of_properties, pretenure_flag)
|
||||
: isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
|
||||
|
||||
// Normalize the elements of the boilerplate to save space if needed.
|
||||
if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
|
||||
if (!use_fast_elements) JSObject::NormalizeElements(boilerplate);
|
||||
|
||||
// Add the constant properties to the boilerplate.
|
||||
int length = boilerplate_description->size();
|
||||
bool should_transform =
|
||||
!is_result_from_cache && boilerplate->HasFastProperties();
|
||||
bool should_normalize = should_transform;
|
||||
if (should_normalize) {
|
||||
// TODO(verwaest): We might not want to ever normalize here.
|
||||
JSObject::NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length,
|
||||
"Boilerplate");
|
||||
}
|
||||
// TODO(verwaest): Support tracking representations in the boilerplate.
|
||||
for (int index = 0; index < length; index++) {
|
||||
Handle<Object> key(boilerplate_description->name(index), isolate);
|
||||
Handle<Object> value(boilerplate_description->value(index), isolate);
|
||||
if (value->IsBoilerplateDescription()) {
|
||||
// The value contains the boilerplate properties of a
|
||||
// simple object or array literal.
|
||||
Handle<BoilerplateDescription> boilerplate =
|
||||
Handle<BoilerplateDescription>::cast(value);
|
||||
if (value->IsFixedArray()) {
|
||||
// The value contains the CompileTimeValue with the boilerplate properties
|
||||
// of a simple object or array literal.
|
||||
Handle<FixedArray> compile_time_value = Handle<FixedArray>::cast(value);
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, value,
|
||||
CreateLiteralBoilerplate(isolate, vector, boilerplate), Object);
|
||||
CreateLiteralBoilerplate(isolate, vector, compile_time_value),
|
||||
Object);
|
||||
}
|
||||
MaybeHandle<Object> maybe_result;
|
||||
uint32_t element_index = 0;
|
||||
@ -92,11 +83,9 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
|
||||
RETURN_ON_EXCEPTION(isolate, maybe_result, Object);
|
||||
}
|
||||
|
||||
// Transform to fast properties if necessary. For object literals with
|
||||
// containing function literals we defer this operation until after all
|
||||
// computed properties have been assigned so that we can generate
|
||||
// constant function properties.
|
||||
if (should_transform) {
|
||||
if (map->is_dictionary_map() && !has_null_prototype) {
|
||||
// TODO(cbruni): avoid making the boilerplate fast again, the clone stub
|
||||
// supports dict-mode objects directly.
|
||||
JSObject::MigrateSlowToFast(boilerplate,
|
||||
boilerplate->map()->unused_property_fields(),
|
||||
"FastLiteral");
|
||||
@ -154,15 +143,16 @@ static MaybeHandle<Object> CreateArrayLiteralBoilerplate(
|
||||
copied_elements_values = fixed_array_values_copy;
|
||||
FOR_WITH_HANDLE_SCOPE(
|
||||
isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
|
||||
if (fixed_array_values->get(i)->IsBoilerplateDescription()) {
|
||||
// The value contains the boilerplate properties of a
|
||||
// simple object or array literal.
|
||||
Handle<BoilerplateDescription> boilerplate(
|
||||
BoilerplateDescription::cast(fixed_array_values->get(i)));
|
||||
if (fixed_array_values->get(i)->IsFixedArray()) {
|
||||
// The value contains the CompileTimeValue with the
|
||||
// boilerplate description of a simple object or
|
||||
// array literal.
|
||||
Handle<FixedArray> compile_time_value(
|
||||
FixedArray::cast(fixed_array_values->get(i)));
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, result,
|
||||
CreateLiteralBoilerplate(isolate, vector, boilerplate),
|
||||
CreateLiteralBoilerplate(isolate, vector, compile_time_value),
|
||||
Object);
|
||||
fixed_array_values_copy->set(i, *result);
|
||||
}
|
||||
@ -178,28 +168,21 @@ static MaybeHandle<Object> CreateArrayLiteralBoilerplate(
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
|
||||
Isolate* isolate, Handle<FeedbackVector> vector,
|
||||
Handle<BoilerplateDescription> array) {
|
||||
Handle<HeapObject> elements = CompileTimeValue::GetElements(array);
|
||||
switch (CompileTimeValue::GetLiteralType(array)) {
|
||||
case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS: {
|
||||
Handle<BoilerplateDescription> props =
|
||||
Handle<BoilerplateDescription>::cast(elements);
|
||||
return CreateObjectLiteralBoilerplate(isolate, vector, props, true);
|
||||
}
|
||||
case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS: {
|
||||
Handle<BoilerplateDescription> props =
|
||||
Handle<BoilerplateDescription>::cast(elements);
|
||||
return CreateObjectLiteralBoilerplate(isolate, vector, props, false);
|
||||
}
|
||||
case CompileTimeValue::ARRAY_LITERAL: {
|
||||
Handle<ConstantElementsPair> elems =
|
||||
Handle<ConstantElementsPair>::cast(elements);
|
||||
return CreateArrayLiteralBoilerplate(isolate, vector, elems);
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return MaybeHandle<Object>();
|
||||
Handle<FixedArray> compile_time_value) {
|
||||
Handle<HeapObject> elements =
|
||||
CompileTimeValue::GetElements(compile_time_value);
|
||||
int flags = CompileTimeValue::GetLiteralTypeFlags(compile_time_value);
|
||||
if (flags == CompileTimeValue::kArrayLiteralFlag) {
|
||||
Handle<ConstantElementsPair> elems =
|
||||
Handle<ConstantElementsPair>::cast(elements);
|
||||
return CreateArrayLiteralBoilerplate(isolate, vector, elems);
|
||||
}
|
||||
Handle<BoilerplateDescription> props =
|
||||
Handle<BoilerplateDescription>::cast(elements);
|
||||
bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
|
||||
bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0;
|
||||
return CreateObjectLiteralBoilerplate(isolate, vector, props,
|
||||
use_fast_elements, has_null_prototype);
|
||||
}
|
||||
|
||||
|
||||
@ -233,8 +216,9 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
|
||||
2);
|
||||
CONVERT_SMI_ARG_CHECKED(flags, 3);
|
||||
Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
|
||||
bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
|
||||
bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
|
||||
bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
|
||||
bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0;
|
||||
|
||||
FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
|
||||
CHECK(literals_slot.ToInt() < vector->slot_count());
|
||||
@ -248,7 +232,7 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, raw_boilerplate,
|
||||
CreateObjectLiteralBoilerplate(isolate, vector, boilerplate_description,
|
||||
should_have_fast_elements));
|
||||
use_fast_elements, has_null_prototype));
|
||||
boilerplate = Handle<JSObject>::cast(raw_boilerplate);
|
||||
|
||||
AllocationSiteCreationContext creation_context(isolate);
|
||||
|
@ -251,18 +251,12 @@ RUNTIME_FUNCTION(Runtime_ObjectCreate) {
|
||||
Handle<Map> map =
|
||||
Map::GetObjectCreateMap(Handle<HeapObject>::cast(prototype));
|
||||
|
||||
bool is_dictionary_map = map->is_dictionary_map();
|
||||
Handle<FixedArray> object_properties;
|
||||
if (is_dictionary_map) {
|
||||
// Allocate the actual properties dictionay up front to avoid invalid object
|
||||
// state.
|
||||
object_properties =
|
||||
NameDictionary::New(isolate, NameDictionary::kInitialCapacity);
|
||||
}
|
||||
// Actually allocate the object.
|
||||
Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
|
||||
if (is_dictionary_map) {
|
||||
object->set_properties(*object_properties);
|
||||
Handle<JSObject> object;
|
||||
if (map->is_dictionary_map()) {
|
||||
object = isolate->factory()->NewSlowJSObjectFromMap(map);
|
||||
} else {
|
||||
object = isolate->factory()->NewJSObjectFromMap(map);
|
||||
}
|
||||
|
||||
// Define the properties if properties was specified and is not undefined.
|
||||
|
@ -14,7 +14,7 @@ parameter count: 1
|
||||
bytecode array length: 6
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(9),
|
||||
/* 34 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(17),
|
||||
/* 51 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@ -34,7 +34,7 @@ bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaSmi), I8(1),
|
||||
B(Star), R(0),
|
||||
/* 45 S> */ B(CreateArrayLiteral), U8(0), U8(3), U8(9),
|
||||
/* 45 S> */ B(CreateArrayLiteral), U8(0), U8(3), U8(17),
|
||||
B(Star), R(2),
|
||||
B(LdaZero),
|
||||
B(Star), R(1),
|
||||
@ -87,7 +87,7 @@ bytecodes: [
|
||||
B(Star), R(2),
|
||||
B(LdaZero),
|
||||
B(Star), R(1),
|
||||
B(CreateArrayLiteral), U8(1), U8(2), U8(9),
|
||||
B(CreateArrayLiteral), U8(1), U8(2), U8(17),
|
||||
B(Star), R(4),
|
||||
B(LdaZero),
|
||||
B(Star), R(3),
|
||||
@ -97,7 +97,7 @@ bytecodes: [
|
||||
B(StaKeyedPropertySloppy), R(2), R(1), U8(10),
|
||||
B(LdaSmi), I8(1),
|
||||
B(Star), R(1),
|
||||
B(CreateArrayLiteral), U8(2), U8(6), U8(9),
|
||||
B(CreateArrayLiteral), U8(2), U8(6), U8(17),
|
||||
B(Star), R(4),
|
||||
B(LdaZero),
|
||||
B(Star), R(3),
|
||||
|
@ -783,7 +783,7 @@ bytecodes: [
|
||||
B(Star), R(0),
|
||||
/* 2591 S> */ B(LdaConstant), U8(255),
|
||||
B(Star), R(0),
|
||||
/* 2601 S> */ B(Wide), B(CreateArrayLiteral), U16(256), U16(2), U8(9),
|
||||
/* 2601 S> */ B(Wide), B(CreateArrayLiteral), U16(256), U16(2), U8(17),
|
||||
/* 2619 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
|
@ -18,7 +18,7 @@ bytecodes: [
|
||||
B(Star), R(1),
|
||||
/* 38 E> */ B(LdaNamedProperty), R(1), U8(1), U8(6),
|
||||
B(Star), R(0),
|
||||
B(CreateArrayLiteral), U8(2), U8(8), U8(9),
|
||||
B(CreateArrayLiteral), U8(2), U8(8), U8(17),
|
||||
B(Star), R(2),
|
||||
/* 39 E> */ B(CallWithSpread), R(0), R(1), U8(2),
|
||||
B(LdaUndefined),
|
||||
@ -47,7 +47,7 @@ bytecodes: [
|
||||
B(Star), R(0),
|
||||
B(LdaZero),
|
||||
B(Star), R(2),
|
||||
B(CreateArrayLiteral), U8(2), U8(8), U8(9),
|
||||
B(CreateArrayLiteral), U8(2), U8(8), U8(17),
|
||||
B(Star), R(3),
|
||||
/* 39 E> */ B(CallWithSpread), R(0), R(1), U8(3),
|
||||
B(LdaUndefined),
|
||||
@ -78,15 +78,15 @@ bytecodes: [
|
||||
B(Star), R(2),
|
||||
B(LdaUndefined),
|
||||
B(Star), R(4),
|
||||
B(CreateArrayLiteral), U8(2), U8(6), U8(9),
|
||||
B(CreateArrayLiteral), U8(2), U8(6), U8(17),
|
||||
B(Star), R(5),
|
||||
B(LdaUndefined),
|
||||
B(Star), R(6),
|
||||
B(CreateArrayLiteral), U8(3), U8(7), U8(9),
|
||||
B(CreateArrayLiteral), U8(3), U8(7), U8(17),
|
||||
B(Star), R(7),
|
||||
B(CallJSRuntime), U8(%spread_iterable), R(6), U8(2),
|
||||
B(Star), R(6),
|
||||
B(CreateArrayLiteral), U8(4), U8(8), U8(9),
|
||||
B(CreateArrayLiteral), U8(4), U8(8), U8(17),
|
||||
B(Star), R(7),
|
||||
B(CallJSRuntime), U8(%spread_arguments), R(4), U8(4),
|
||||
B(Star), R(4),
|
||||
|
@ -77,7 +77,7 @@ bytecodes: [
|
||||
/* 10 E> */ B(StackCheck),
|
||||
/* 15 S> */ B(LdaUndefined),
|
||||
B(Star), R(0),
|
||||
B(CreateArrayLiteral), U8(0), U8(2), U8(9),
|
||||
B(CreateArrayLiteral), U8(0), U8(2), U8(17),
|
||||
B(Star), R(1),
|
||||
B(CallJSRuntime), U8(%spread_iterable), R(0), U8(2),
|
||||
/* 44 S> */ B(Return),
|
||||
|
@ -261,7 +261,7 @@ bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 44 S> */ B(LdaSmi), I8(1),
|
||||
B(Star), R(0),
|
||||
/* 55 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(9),
|
||||
/* 55 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(17),
|
||||
B(Star), R(1),
|
||||
/* 63 S> */ B(Ldar), R(0),
|
||||
B(ToNumber), R(3), U8(3),
|
||||
|
@ -63,7 +63,7 @@ bytecodes: [
|
||||
B(StaContextSlot), R(1), U8(9), U8(0),
|
||||
B(Mov), R(context), R(11),
|
||||
B(Mov), R(context), R(12),
|
||||
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(9),
|
||||
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(17),
|
||||
B(Star), R(13),
|
||||
B(LdaNamedProperty), R(13), U8(2), U8(7),
|
||||
B(JumpIfUndefined), U8(17),
|
||||
@ -539,7 +539,7 @@ bytecodes: [
|
||||
B(StaContextSlot), R(1), U8(9), U8(0),
|
||||
B(Mov), R(context), R(11),
|
||||
B(Mov), R(context), R(12),
|
||||
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(9),
|
||||
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(17),
|
||||
B(Star), R(13),
|
||||
B(LdaNamedProperty), R(13), U8(2), U8(7),
|
||||
B(JumpIfUndefined), U8(17),
|
||||
@ -1047,7 +1047,7 @@ bytecodes: [
|
||||
B(StaContextSlot), R(1), U8(9), U8(0),
|
||||
B(Mov), R(context), R(11),
|
||||
B(Mov), R(context), R(12),
|
||||
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(9),
|
||||
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(17),
|
||||
B(Star), R(13),
|
||||
B(LdaNamedProperty), R(13), U8(2), U8(7),
|
||||
B(JumpIfUndefined), U8(17),
|
||||
@ -1529,7 +1529,7 @@ bytecodes: [
|
||||
B(StaCurrentContextSlot), U8(9),
|
||||
B(Mov), R(context), R(10),
|
||||
B(Mov), R(context), R(11),
|
||||
/* 68 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(9),
|
||||
/* 68 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(17),
|
||||
B(Star), R(12),
|
||||
B(LdaNamedProperty), R(12), U8(2), U8(4),
|
||||
B(Star), R(13),
|
||||
|
@ -107,7 +107,7 @@ bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaZero),
|
||||
B(Star), R(0),
|
||||
/* 59 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(9),
|
||||
/* 59 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(17),
|
||||
B(JumpIfUndefined), U8(46),
|
||||
B(JumpIfNull), U8(44),
|
||||
B(ToObject), R(3),
|
||||
@ -152,7 +152,7 @@ bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(1),
|
||||
B(Mov), R(1), R(0),
|
||||
/* 77 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(9),
|
||||
/* 77 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(17),
|
||||
B(JumpIfUndefined), U8(72),
|
||||
B(JumpIfNull), U8(70),
|
||||
B(ToObject), R(1),
|
||||
@ -205,9 +205,9 @@ parameter count: 1
|
||||
bytecode array length: 62
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(9),
|
||||
/* 42 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(17),
|
||||
B(Star), R(0),
|
||||
/* 72 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(9),
|
||||
/* 72 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(17),
|
||||
B(JumpIfUndefined), U8(49),
|
||||
B(JumpIfNull), U8(47),
|
||||
B(ToObject), R(1),
|
||||
|
@ -18,7 +18,7 @@ bytecodes: [
|
||||
B(Star), R(4),
|
||||
B(Mov), R(context), R(11),
|
||||
B(Mov), R(context), R(12),
|
||||
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(9),
|
||||
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(17),
|
||||
B(Star), R(13),
|
||||
B(LdaNamedProperty), R(13), U8(1), U8(3),
|
||||
B(Star), R(14),
|
||||
@ -305,7 +305,7 @@ bytecodes: [
|
||||
B(Star), R(4),
|
||||
B(Mov), R(context), R(11),
|
||||
B(Mov), R(context), R(12),
|
||||
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(9),
|
||||
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(17),
|
||||
B(Star), R(13),
|
||||
B(LdaNamedProperty), R(13), U8(1), U8(3),
|
||||
B(Star), R(14),
|
||||
@ -454,7 +454,7 @@ bytecodes: [
|
||||
B(Star), R(3),
|
||||
B(Mov), R(context), R(10),
|
||||
B(Mov), R(context), R(11),
|
||||
/* 77 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(9),
|
||||
/* 77 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(17),
|
||||
B(Star), R(12),
|
||||
B(LdaNamedProperty), R(12), U8(2), U8(4),
|
||||
B(Star), R(13),
|
||||
|
@ -349,7 +349,7 @@ bytecodes: [
|
||||
B(StaContextSlot), R(1), U8(9), U8(0),
|
||||
B(Mov), R(context), R(10),
|
||||
B(Mov), R(context), R(11),
|
||||
/* 30 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(9),
|
||||
/* 30 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(17),
|
||||
B(Star), R(12),
|
||||
B(LdaNamedProperty), R(12), U8(2), U8(3),
|
||||
B(Star), R(13),
|
||||
|
@ -35,7 +35,7 @@ bytecodes: [
|
||||
B(Star), R(0),
|
||||
B(Star), R(1),
|
||||
B(Star), R(2),
|
||||
/* 89 S> */ B(CreateArrayLiteral), U8(1), U8(5), U8(9),
|
||||
/* 89 S> */ B(CreateArrayLiteral), U8(1), U8(5), U8(17),
|
||||
B(Star), R(4),
|
||||
B(Ldar), R(2),
|
||||
/* 89 E> */ B(ConstructWithSpread), R(2), R(4), U8(1),
|
||||
@ -81,7 +81,7 @@ bytecodes: [
|
||||
B(Star), R(2),
|
||||
/* 89 S> */ B(LdaZero),
|
||||
B(Star), R(4),
|
||||
B(CreateArrayLiteral), U8(1), U8(5), U8(9),
|
||||
B(CreateArrayLiteral), U8(1), U8(5), U8(17),
|
||||
B(Star), R(5),
|
||||
B(Ldar), R(2),
|
||||
/* 89 E> */ B(ConstructWithSpread), R(2), R(4), U8(2),
|
||||
@ -129,15 +129,15 @@ bytecodes: [
|
||||
B(Star), R(3),
|
||||
B(LdaUndefined),
|
||||
B(Star), R(5),
|
||||
/* 93 E> */ B(CreateArrayLiteral), U8(1), U8(3), U8(9),
|
||||
/* 93 E> */ B(CreateArrayLiteral), U8(1), U8(3), U8(17),
|
||||
B(Star), R(6),
|
||||
B(LdaUndefined),
|
||||
B(Star), R(7),
|
||||
B(CreateArrayLiteral), U8(2), U8(4), U8(9),
|
||||
B(CreateArrayLiteral), U8(2), U8(4), U8(17),
|
||||
B(Star), R(8),
|
||||
B(CallJSRuntime), U8(%spread_iterable), R(7), U8(2),
|
||||
B(Star), R(7),
|
||||
B(CreateArrayLiteral), U8(3), U8(5), U8(9),
|
||||
B(CreateArrayLiteral), U8(3), U8(5), U8(17),
|
||||
B(Star), R(8),
|
||||
B(CallJSRuntime), U8(%spread_arguments), R(5), U8(4),
|
||||
B(Star), R(5),
|
||||
|
@ -14,7 +14,7 @@ parameter count: 1
|
||||
bytecode array length: 9
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(35), R(0),
|
||||
/* 34 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(67), R(0),
|
||||
B(Ldar), R(0),
|
||||
/* 46 S> */ B(Return),
|
||||
]
|
||||
@ -262,17 +262,13 @@ handlers: [
|
||||
snippet: "
|
||||
return { __proto__: null };
|
||||
"
|
||||
frame size: 3
|
||||
frame size: 1
|
||||
parameter count: 1
|
||||
bytecode array length: 20
|
||||
bytecode array length: 9
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(35), R(0),
|
||||
B(LdaNull),
|
||||
B(Star), R(2),
|
||||
B(Mov), R(0), R(1),
|
||||
B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2),
|
||||
B(Ldar), R(1),
|
||||
/* 34 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(75), R(0),
|
||||
B(Ldar), R(0),
|
||||
/* 62 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@ -292,7 +288,7 @@ bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaConstant), U8(0),
|
||||
B(Star), R(0),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(2), U8(35), R(1),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(2), U8(67), R(1),
|
||||
/* 60 E> */ B(ToName), R(2),
|
||||
B(LdaSmi), I8(1),
|
||||
B(Star), R(3),
|
||||
@ -346,12 +342,12 @@ bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaConstant), U8(0),
|
||||
B(Star), R(0),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(3), U8(35), R(1),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(3), U8(67), R(1),
|
||||
/* 60 E> */ B(ToName), R(2),
|
||||
B(LdaSmi), I8(1),
|
||||
B(Star), R(3),
|
||||
B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(4),
|
||||
B(CreateObjectLiteral), U8(1), U8(2), U8(35), R(4),
|
||||
B(CreateObjectLiteral), U8(1), U8(2), U8(67), R(4),
|
||||
B(Mov), R(1), R(2),
|
||||
B(Mov), R(4), R(3),
|
||||
B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(2), U8(2),
|
||||
@ -376,7 +372,7 @@ bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaConstant), U8(0),
|
||||
B(Star), R(0),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(4), U8(35), R(1),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(4), U8(67), R(1),
|
||||
/* 60 E> */ B(ToName), R(2),
|
||||
B(LdaConstant), U8(2),
|
||||
B(Star), R(3),
|
||||
|
@ -119,14 +119,14 @@ bytecodes: [
|
||||
B(Star), R(5),
|
||||
B(LdaUndefined),
|
||||
B(Star), R(6),
|
||||
B(CreateArrayLiteral), U8(0), U8(2), U8(9),
|
||||
B(CreateArrayLiteral), U8(0), U8(2), U8(17),
|
||||
B(Star), R(7),
|
||||
B(LdaUndefined),
|
||||
B(Star), R(8),
|
||||
B(Mov), R(2), R(9),
|
||||
/* 152 E> */ B(CallJSRuntime), U8(%spread_iterable), R(8), U8(2),
|
||||
B(Star), R(8),
|
||||
B(CreateArrayLiteral), U8(1), U8(3), U8(9),
|
||||
B(CreateArrayLiteral), U8(1), U8(3), U8(17),
|
||||
B(Star), R(9),
|
||||
B(CallJSRuntime), U8(%spread_arguments), R(6), U8(4),
|
||||
B(Star), R(6),
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user