Ensure object literal element boilerplates aren't modified.
A bug allows JSObject literals with elements to have the elements in the boilerplate modified. BUG=466993 LOG=N Review URL: https://codereview.chromium.org/1037273002 Cr-Commit-Position: refs/heads/master@{#27511}
This commit is contained in:
parent
f303b81bde
commit
7c347c545e
@ -1698,21 +1698,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
|
||||
__ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
|
||||
__ mov(r1, Operand(constant_properties));
|
||||
int flags = expr->fast_elements()
|
||||
? ObjectLiteral::kFastElements
|
||||
: ObjectLiteral::kNoFlags;
|
||||
flags |= expr->has_function()
|
||||
? ObjectLiteral::kHasFunction
|
||||
: ObjectLiteral::kNoFlags;
|
||||
int flags = expr->ComputeFlags();
|
||||
__ mov(r0, Operand(Smi::FromInt(flags)));
|
||||
int properties_count = constant_properties->length() / 2;
|
||||
if (expr->may_store_doubles() || expr->depth() > 1 ||
|
||||
masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements ||
|
||||
properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
|
||||
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||
__ Push(r3, r2, r1, r0);
|
||||
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
||||
} else {
|
||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
||||
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
@ -1904,17 +1896,10 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
|
||||
expr->BuildConstantElements(isolate());
|
||||
int flags = expr->depth() == 1
|
||||
? ArrayLiteral::kShallowElements
|
||||
: ArrayLiteral::kNoFlags;
|
||||
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
Handle<FixedArray> constant_elements = expr->constant_elements();
|
||||
DCHECK_EQ(2, constant_elements->length());
|
||||
ElementsKind constant_elements_kind =
|
||||
static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
|
||||
bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind);
|
||||
bool has_fast_elements =
|
||||
IsFastObjectElementsKind(expr->constant_elements_kind());
|
||||
Handle<FixedArrayBase> constant_elements_values(
|
||||
FixedArrayBase::cast(constant_elements->get(1)));
|
||||
|
||||
@ -1929,8 +1914,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
__ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
|
||||
__ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
|
||||
__ mov(r1, Operand(constant_elements));
|
||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
||||
__ mov(r0, Operand(Smi::FromInt(flags)));
|
||||
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||
__ mov(r0, Operand(Smi::FromInt(expr->ComputeFlags())));
|
||||
__ Push(r3, r2, r1, r0);
|
||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||
} else {
|
||||
@ -1940,6 +1925,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
|
||||
bool result_saved = false; // Is the result saved to the stack?
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
|
||||
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||
// them into the newly cloned array.
|
||||
@ -1956,7 +1943,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
VisitForAccumulatorValue(subexpr);
|
||||
|
||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
||||
if (has_fast_elements) {
|
||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||
__ ldr(r6, MemOperand(sp, kPointerSize)); // Copy of array literal.
|
||||
__ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
|
||||
|
@ -1677,23 +1677,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset));
|
||||
__ Mov(x2, Smi::FromInt(expr->literal_index()));
|
||||
__ Mov(x1, Operand(constant_properties));
|
||||
int flags = expr->fast_elements()
|
||||
? ObjectLiteral::kFastElements
|
||||
: ObjectLiteral::kNoFlags;
|
||||
flags |= expr->has_function()
|
||||
? ObjectLiteral::kHasFunction
|
||||
: ObjectLiteral::kNoFlags;
|
||||
int flags = expr->ComputeFlags();
|
||||
__ Mov(x0, Smi::FromInt(flags));
|
||||
int properties_count = constant_properties->length() / 2;
|
||||
const int max_cloned_properties =
|
||||
FastCloneShallowObjectStub::kMaximumClonedProperties;
|
||||
if (expr->may_store_doubles() || expr->depth() > 1 ||
|
||||
masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements ||
|
||||
properties_count > max_cloned_properties) {
|
||||
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||
__ Push(x3, x2, x1, x0);
|
||||
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
||||
} else {
|
||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
||||
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
@ -1885,18 +1875,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
|
||||
expr->BuildConstantElements(isolate());
|
||||
int flags = (expr->depth() == 1) ? ArrayLiteral::kShallowElements
|
||||
: ArrayLiteral::kNoFlags;
|
||||
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
Handle<FixedArray> constant_elements = expr->constant_elements();
|
||||
DCHECK_EQ(2, constant_elements->length());
|
||||
ElementsKind constant_elements_kind =
|
||||
static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
|
||||
bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind);
|
||||
Handle<FixedArrayBase> constant_elements_values(
|
||||
FixedArrayBase::cast(constant_elements->get(1)));
|
||||
bool has_fast_elements =
|
||||
IsFastObjectElementsKind(expr->constant_elements_kind());
|
||||
|
||||
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
||||
if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
|
||||
@ -1909,8 +1890,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
__ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset));
|
||||
__ Mov(x2, Smi::FromInt(expr->literal_index()));
|
||||
__ Mov(x1, Operand(constant_elements));
|
||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
||||
__ Mov(x0, Smi::FromInt(flags));
|
||||
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||
__ Mov(x0, Smi::FromInt(expr->ComputeFlags()));
|
||||
__ Push(x3, x2, x1, x0);
|
||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||
} else {
|
||||
@ -1920,6 +1901,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
|
||||
bool result_saved = false; // Is the result saved to the stack?
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
|
||||
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||
// them into the newly cloned array.
|
||||
@ -1936,7 +1919,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
VisitForAccumulatorValue(subexpr);
|
||||
|
||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
||||
if (has_fast_elements) {
|
||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||
__ Peek(x6, kPointerSize); // Copy of array literal.
|
||||
__ Ldr(x1, FieldMemOperand(x6, JSObject::kElementsOffset));
|
||||
|
@ -368,6 +368,7 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
|
||||
constant_properties_ = constant_properties;
|
||||
fast_elements_ =
|
||||
(max_element_index <= 32) || ((2 * elements) >= max_element_index);
|
||||
has_elements_ = elements > 0;
|
||||
set_is_simple(is_simple);
|
||||
set_depth(depth_acc);
|
||||
}
|
||||
|
24
src/ast.h
24
src/ast.h
@ -1482,10 +1482,12 @@ class ObjectLiteral FINAL : public MaterializedLiteral {
|
||||
Handle<FixedArray> constant_properties() const {
|
||||
return constant_properties_;
|
||||
}
|
||||
int properties_count() const { return constant_properties_->length() / 2; }
|
||||
ZoneList<Property*>* properties() const { return properties_; }
|
||||
bool fast_elements() const { return fast_elements_; }
|
||||
bool may_store_doubles() const { return may_store_doubles_; }
|
||||
bool has_function() const { return has_function_; }
|
||||
bool has_elements() const { return has_elements_; }
|
||||
|
||||
// Decide if a property should be in the object boilerplate.
|
||||
static bool IsBoilerplateProperty(Property* property);
|
||||
@ -1499,16 +1501,20 @@ class ObjectLiteral FINAL : public MaterializedLiteral {
|
||||
void CalculateEmitStore(Zone* zone);
|
||||
|
||||
// Assemble bitfield of flags for the CreateObjectLiteral helper.
|
||||
int ComputeFlags() const {
|
||||
int ComputeFlags(bool disable_mementos = false) const {
|
||||
int flags = fast_elements() ? kFastElements : kNoFlags;
|
||||
flags |= has_function() ? kHasFunction : kNoFlags;
|
||||
if (disable_mementos) {
|
||||
flags |= kDisableMementos;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
enum Flags {
|
||||
kNoFlags = 0,
|
||||
kFastElements = 1,
|
||||
kHasFunction = 1 << 1
|
||||
kHasFunction = 1 << 1,
|
||||
kDisableMementos = 1 << 2
|
||||
};
|
||||
|
||||
struct Accessors: public ZoneObject {
|
||||
@ -1533,6 +1539,7 @@ class ObjectLiteral FINAL : public MaterializedLiteral {
|
||||
properties_(properties),
|
||||
boilerplate_properties_(boilerplate_properties),
|
||||
fast_elements_(false),
|
||||
has_elements_(false),
|
||||
may_store_doubles_(false),
|
||||
has_function_(has_function) {}
|
||||
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
|
||||
@ -1543,6 +1550,7 @@ class ObjectLiteral FINAL : public MaterializedLiteral {
|
||||
ZoneList<Property*>* properties_;
|
||||
int boilerplate_properties_;
|
||||
bool fast_elements_;
|
||||
bool has_elements_;
|
||||
bool may_store_doubles_;
|
||||
bool has_function_;
|
||||
};
|
||||
@ -1578,6 +1586,12 @@ class ArrayLiteral FINAL : public MaterializedLiteral {
|
||||
DECLARE_NODE_TYPE(ArrayLiteral)
|
||||
|
||||
Handle<FixedArray> constant_elements() const { return constant_elements_; }
|
||||
ElementsKind constant_elements_kind() const {
|
||||
DCHECK_EQ(2, constant_elements_->length());
|
||||
return static_cast<ElementsKind>(
|
||||
Smi::cast(constant_elements_->get(0))->value());
|
||||
}
|
||||
|
||||
ZoneList<Expression*>* values() const { return values_; }
|
||||
|
||||
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
|
||||
@ -1593,9 +1607,11 @@ class ArrayLiteral FINAL : public MaterializedLiteral {
|
||||
void BuildConstantElements(Isolate* isolate);
|
||||
|
||||
// Assemble bitfield of flags for the CreateArrayLiteral helper.
|
||||
int ComputeFlags() const {
|
||||
int ComputeFlags(bool disable_mementos = false) const {
|
||||
int flags = depth() == 1 ? kShallowElements : kNoFlags;
|
||||
flags |= ArrayLiteral::kDisableMementos;
|
||||
if (disable_mementos) {
|
||||
flags |= kDisableMementos;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
@ -1627,7 +1627,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
|
||||
Node* literal_index = jsgraph()->Constant(expr->literal_index());
|
||||
Node* constants = jsgraph()->Constant(expr->constant_properties());
|
||||
Node* flags = jsgraph()->Constant(expr->ComputeFlags());
|
||||
Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
|
||||
const Operator* op =
|
||||
javascript()->CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
||||
Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
|
||||
@ -1819,7 +1819,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
|
||||
Node* literal_index = jsgraph()->Constant(expr->literal_index());
|
||||
Node* constants = jsgraph()->Constant(expr->constant_elements());
|
||||
Node* flags = jsgraph()->Constant(expr->ComputeFlags());
|
||||
Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
|
||||
const Operator* op =
|
||||
javascript()->CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||
Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
|
||||
|
@ -415,6 +415,27 @@ void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
|
||||
}
|
||||
|
||||
|
||||
bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime(
|
||||
ObjectLiteral* expr) const {
|
||||
// FastCloneShallowObjectStub doesn't copy elements, and object literals don't
|
||||
// support copy-on-write (COW) elements for now.
|
||||
// TODO(mvstanton): make object literals support COW elements.
|
||||
return expr->may_store_doubles() || expr->depth() > 1 ||
|
||||
masm()->serializer_enabled() ||
|
||||
expr->ComputeFlags() != ObjectLiteral::kFastElements ||
|
||||
expr->has_elements() ||
|
||||
expr->properties_count() >
|
||||
FastCloneShallowObjectStub::kMaximumClonedProperties;
|
||||
}
|
||||
|
||||
|
||||
bool FullCodeGenerator::MustCreateArrayLiteralWithRuntime(
|
||||
ArrayLiteral* expr) const {
|
||||
return expr->depth() > 1 ||
|
||||
expr->values()->length() > JSObject::kInitialMaxFastElementArray;
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::Initialize() {
|
||||
InitializeAstVisitor(info_->isolate(), info_->zone());
|
||||
// The generation of debug code must match between the snapshot code and the
|
||||
|
@ -715,7 +715,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
loop_depth_--;
|
||||
}
|
||||
|
||||
MacroAssembler* masm() { return masm_; }
|
||||
MacroAssembler* masm() const { return masm_; }
|
||||
|
||||
class ExpressionContext;
|
||||
const ExpressionContext* context() { return context_; }
|
||||
@ -759,6 +759,9 @@ class FullCodeGenerator: public AstVisitor {
|
||||
void PopulateDeoptimizationData(Handle<Code> code);
|
||||
void PopulateTypeFeedbackInfo(Handle<Code> code);
|
||||
|
||||
bool MustCreateObjectLiteralWithRuntime(ObjectLiteral* expr) const;
|
||||
bool MustCreateArrayLiteralWithRuntime(ArrayLiteral* expr) const;
|
||||
|
||||
Handle<HandlerTable> handler_table() { return handler_table_; }
|
||||
|
||||
struct BailoutEntry {
|
||||
|
@ -5552,19 +5552,13 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
Handle<FixedArray> closure_literals(closure->literals(), isolate());
|
||||
Handle<FixedArray> constant_properties = expr->constant_properties();
|
||||
int literal_index = expr->literal_index();
|
||||
int flags = expr->fast_elements()
|
||||
? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
|
||||
flags |= expr->has_function()
|
||||
? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
|
||||
int flags = expr->ComputeFlags(true);
|
||||
|
||||
Add<HPushArguments>(Add<HConstant>(closure_literals),
|
||||
Add<HConstant>(literal_index),
|
||||
Add<HConstant>(constant_properties),
|
||||
Add<HConstant>(flags));
|
||||
|
||||
// TODO(mvstanton): Add a flag to turn off creation of any
|
||||
// AllocationMementos for this call: we are in crankshaft and should have
|
||||
// learned enough about transition behavior to stop emitting mementos.
|
||||
Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
|
||||
literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
|
||||
Runtime::FunctionForId(function_id),
|
||||
@ -5723,10 +5717,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
// pass an empty fixed array to the runtime function instead.
|
||||
Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
|
||||
int literal_index = expr->literal_index();
|
||||
int flags = expr->depth() == 1
|
||||
? ArrayLiteral::kShallowElements
|
||||
: ArrayLiteral::kNoFlags;
|
||||
flags |= ArrayLiteral::kDisableMementos;
|
||||
int flags = expr->ComputeFlags(true);
|
||||
|
||||
Add<HPushArguments>(Add<HConstant>(literals),
|
||||
Add<HConstant>(literal_index),
|
||||
|
@ -1622,17 +1622,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
|
||||
expr->BuildConstantProperties(isolate());
|
||||
Handle<FixedArray> constant_properties = expr->constant_properties();
|
||||
int flags = expr->fast_elements()
|
||||
? ObjectLiteral::kFastElements
|
||||
: ObjectLiteral::kNoFlags;
|
||||
flags |= expr->has_function()
|
||||
? ObjectLiteral::kHasFunction
|
||||
: ObjectLiteral::kNoFlags;
|
||||
int properties_count = constant_properties->length() / 2;
|
||||
if (expr->may_store_doubles() || expr->depth() > 1 ||
|
||||
masm()->serializer_enabled() ||
|
||||
flags != ObjectLiteral::kFastElements ||
|
||||
properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
|
||||
int flags = expr->ComputeFlags();
|
||||
// If any of the keys would store to the elements array, then we shouldn't
|
||||
// allow it.
|
||||
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
|
||||
__ push(Immediate(Smi::FromInt(expr->literal_index())));
|
||||
@ -1645,7 +1638,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
|
||||
__ mov(ecx, Immediate(constant_properties));
|
||||
__ mov(edx, Immediate(Smi::FromInt(flags)));
|
||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
||||
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
@ -1824,20 +1817,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
|
||||
expr->BuildConstantElements(isolate());
|
||||
int flags = expr->depth() == 1
|
||||
? ArrayLiteral::kShallowElements
|
||||
: ArrayLiteral::kNoFlags;
|
||||
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
Handle<FixedArray> constant_elements = expr->constant_elements();
|
||||
DCHECK_EQ(2, constant_elements->length());
|
||||
ElementsKind constant_elements_kind =
|
||||
static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
|
||||
bool has_constant_fast_elements =
|
||||
IsFastObjectElementsKind(constant_elements_kind);
|
||||
Handle<FixedArrayBase> constant_elements_values(
|
||||
FixedArrayBase::cast(constant_elements->get(1)));
|
||||
IsFastObjectElementsKind(expr->constant_elements_kind());
|
||||
|
||||
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
||||
if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
|
||||
@ -1846,12 +1828,12 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
|
||||
}
|
||||
|
||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
||||
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
|
||||
__ push(Immediate(Smi::FromInt(expr->literal_index())));
|
||||
__ push(Immediate(constant_elements));
|
||||
__ push(Immediate(Smi::FromInt(flags)));
|
||||
__ push(Immediate(Smi::FromInt(expr->ComputeFlags())));
|
||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||
} else {
|
||||
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
@ -1864,6 +1846,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
|
||||
bool result_saved = false; // Is the result saved to the stack?
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
|
||||
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||
// them into the newly cloned array.
|
||||
@ -1880,7 +1864,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
VisitForAccumulatorValue(subexpr);
|
||||
|
||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
||||
if (has_constant_fast_elements) {
|
||||
// Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
|
||||
// cannot transition and don't need to call the runtime stub.
|
||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||
|
@ -1684,21 +1684,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
|
||||
__ li(a2, Operand(Smi::FromInt(expr->literal_index())));
|
||||
__ li(a1, Operand(constant_properties));
|
||||
int flags = expr->fast_elements()
|
||||
? ObjectLiteral::kFastElements
|
||||
: ObjectLiteral::kNoFlags;
|
||||
flags |= expr->has_function()
|
||||
? ObjectLiteral::kHasFunction
|
||||
: ObjectLiteral::kNoFlags;
|
||||
__ li(a0, Operand(Smi::FromInt(flags)));
|
||||
int properties_count = constant_properties->length() / 2;
|
||||
if (expr->may_store_doubles() || expr->depth() > 1 ||
|
||||
masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements ||
|
||||
properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
|
||||
__ li(a0, Operand(Smi::FromInt(expr->ComputeFlags())));
|
||||
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||
__ Push(a3, a2, a1, a0);
|
||||
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
||||
} else {
|
||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
||||
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
@ -1890,21 +1881,10 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
|
||||
expr->BuildConstantElements(isolate());
|
||||
int flags = expr->depth() == 1
|
||||
? ArrayLiteral::kShallowElements
|
||||
: ArrayLiteral::kNoFlags;
|
||||
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
|
||||
Handle<FixedArray> constant_elements = expr->constant_elements();
|
||||
DCHECK_EQ(2, constant_elements->length());
|
||||
ElementsKind constant_elements_kind =
|
||||
static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
|
||||
bool has_fast_elements =
|
||||
IsFastObjectElementsKind(constant_elements_kind);
|
||||
Handle<FixedArrayBase> constant_elements_values(
|
||||
FixedArrayBase::cast(constant_elements->get(1)));
|
||||
IsFastObjectElementsKind(expr->constant_elements_kind());
|
||||
|
||||
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
||||
if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
|
||||
@ -1918,8 +1898,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
__ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
|
||||
__ li(a2, Operand(Smi::FromInt(expr->literal_index())));
|
||||
__ li(a1, Operand(constant_elements));
|
||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
||||
__ li(a0, Operand(Smi::FromInt(flags)));
|
||||
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||
__ li(a0, Operand(Smi::FromInt(expr->ComputeFlags())));
|
||||
__ Push(a3, a2, a1, a0);
|
||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||
} else {
|
||||
@ -1929,6 +1909,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
|
||||
bool result_saved = false; // Is the result saved to the stack?
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
|
||||
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||
// them into the newly cloned array.
|
||||
@ -1946,7 +1928,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
|
||||
VisitForAccumulatorValue(subexpr);
|
||||
|
||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
||||
if (has_fast_elements) {
|
||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||
__ lw(t2, MemOperand(sp, kPointerSize)); // Copy of array literal.
|
||||
__ lw(a1, FieldMemOperand(t2, JSObject::kElementsOffset));
|
||||
|
@ -237,6 +237,7 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
|
||||
CONVERT_SMI_ARG_CHECKED(flags, 3);
|
||||
bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
|
||||
bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
|
||||
bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
|
||||
|
||||
RUNTIME_ASSERT(literals_index >= 0 && literals_index < literals->length());
|
||||
|
||||
@ -267,7 +268,7 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
|
||||
Handle<JSObject>(JSObject::cast(site->transition_info()), isolate);
|
||||
}
|
||||
|
||||
AllocationSiteUsageContext usage_context(isolate, site, true);
|
||||
AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
|
||||
usage_context.EnterNewScope();
|
||||
MaybeHandle<Object> maybe_copy =
|
||||
JSObject::DeepCopy(boilerplate, &usage_context);
|
||||
|
@ -1657,16 +1657,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
|
||||
expr->BuildConstantProperties(isolate());
|
||||
Handle<FixedArray> constant_properties = expr->constant_properties();
|
||||
int flags = expr->fast_elements()
|
||||
? ObjectLiteral::kFastElements
|
||||
: ObjectLiteral::kNoFlags;
|
||||
flags |= expr->has_function()
|
||||
? ObjectLiteral::kHasFunction
|
||||
: ObjectLiteral::kNoFlags;
|
||||
int properties_count = constant_properties->length() / 2;
|
||||
if (expr->may_store_doubles() || expr->depth() > 1 ||
|
||||
masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements ||
|
||||
properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
|
||||
int flags = expr->ComputeFlags();
|
||||
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||
__ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
|
||||
__ Push(Smi::FromInt(expr->literal_index()));
|
||||
@ -1679,7 +1671,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ Move(rbx, Smi::FromInt(expr->literal_index()));
|
||||
__ Move(rcx, constant_properties);
|
||||
__ Move(rdx, Smi::FromInt(flags));
|
||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
||||
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
@ -1858,20 +1850,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
|
||||
expr->BuildConstantElements(isolate());
|
||||
int flags = expr->depth() == 1
|
||||
? ArrayLiteral::kShallowElements
|
||||
: ArrayLiteral::kNoFlags;
|
||||
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
Handle<FixedArray> constant_elements = expr->constant_elements();
|
||||
DCHECK_EQ(2, constant_elements->length());
|
||||
ElementsKind constant_elements_kind =
|
||||
static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
|
||||
bool has_constant_fast_elements =
|
||||
IsFastObjectElementsKind(constant_elements_kind);
|
||||
Handle<FixedArrayBase> constant_elements_values(
|
||||
FixedArrayBase::cast(constant_elements->get(1)));
|
||||
IsFastObjectElementsKind(expr->constant_elements_kind());
|
||||
|
||||
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
||||
if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
|
||||
@ -1880,12 +1861,12 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
|
||||
}
|
||||
|
||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
||||
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||
__ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
|
||||
__ Push(Smi::FromInt(expr->literal_index()));
|
||||
__ Push(constant_elements);
|
||||
__ Push(Smi::FromInt(flags));
|
||||
__ Push(Smi::FromInt(expr->ComputeFlags()));
|
||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||
} else {
|
||||
__ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
@ -1898,6 +1879,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
|
||||
bool result_saved = false; // Is the result saved to the stack?
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
int length = subexprs->length();
|
||||
|
||||
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||
// them into the newly cloned array.
|
||||
@ -1914,7 +1897,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
VisitForAccumulatorValue(subexpr);
|
||||
|
||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
||||
if (has_constant_fast_elements) {
|
||||
// Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
|
||||
// cannot transition and don't need to call the runtime stub.
|
||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||
|
18
test/mjsunit/regress/regress-466993.js
Normal file
18
test/mjsunit/regress/regress-466993.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
var test = function() {
|
||||
var a = {"1": false, "2": false, "3": false, "4": false};
|
||||
assertEquals(false, a[1]);
|
||||
a[1] = true;
|
||||
};
|
||||
test();
|
||||
test();
|
||||
test();
|
||||
%OptimizeFunctionOnNextCall(test);
|
||||
test();
|
||||
test();
|
||||
test();
|
Loading…
Reference in New Issue
Block a user