[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:
cbruni 2017-04-27 07:48:32 -07:00 committed by Commit bot
parent dc713be87d
commit 3f73fecb13
32 changed files with 1569 additions and 336 deletions

View File

@ -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();

View File

@ -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;
}

View File

@ -24,28 +24,24 @@ Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
Factory* factory = isolate->factory();
DCHECK(IsCompileTimeValue(expression));
Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
if (expression->IsObjectLiteral()) {
ObjectLiteral* object_literal = expression->AsObjectLiteral();
if (object_literal != NULL) {
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) {

View File

@ -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);

View File

@ -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);
}
// Store the map for the %StringPrototype% after the natives has been compiled
// and the String function has been set up.

View File

@ -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),
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);

View File

@ -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) {

View File

@ -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,

View File

@ -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) \

View File

@ -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;

View File

@ -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();

View File

@ -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> {};

View File

@ -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]);

View File

@ -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.

View File

@ -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,

View File

@ -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();

View File

@ -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 {

View File

@ -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<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);
}
default:
UNREACHABLE();
return MaybeHandle<Object>();
}
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);

View File

@ -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.

View File

@ -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),

View File

@ -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: [

View File

@ -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),

View File

@ -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),

View File

@ -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),

View File

@ -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),

View File

@ -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),

View File

@ -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),

View File

@ -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),

View File

@ -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),

View File

@ -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),

View File

@ -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