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));
|
__ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
|
||||||
__ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
|
__ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
|
||||||
__ mov(r1, Operand(constant_properties));
|
__ mov(r1, Operand(constant_properties));
|
||||||
int flags = expr->fast_elements()
|
int flags = expr->ComputeFlags();
|
||||||
? ObjectLiteral::kFastElements
|
|
||||||
: ObjectLiteral::kNoFlags;
|
|
||||||
flags |= expr->has_function()
|
|
||||||
? ObjectLiteral::kHasFunction
|
|
||||||
: ObjectLiteral::kNoFlags;
|
|
||||||
__ mov(r0, Operand(Smi::FromInt(flags)));
|
__ mov(r0, Operand(Smi::FromInt(flags)));
|
||||||
int properties_count = constant_properties->length() / 2;
|
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||||
if (expr->may_store_doubles() || expr->depth() > 1 ||
|
|
||||||
masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements ||
|
|
||||||
properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
|
|
||||||
__ Push(r3, r2, r1, r0);
|
__ Push(r3, r2, r1, r0);
|
||||||
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
||||||
} else {
|
} else {
|
||||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
}
|
}
|
||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
@ -1904,17 +1896,10 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||||
|
|
||||||
expr->BuildConstantElements(isolate());
|
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();
|
Handle<FixedArray> constant_elements = expr->constant_elements();
|
||||||
DCHECK_EQ(2, constant_elements->length());
|
bool has_fast_elements =
|
||||||
ElementsKind constant_elements_kind =
|
IsFastObjectElementsKind(expr->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(
|
Handle<FixedArrayBase> constant_elements_values(
|
||||||
FixedArrayBase::cast(constant_elements->get(1)));
|
FixedArrayBase::cast(constant_elements->get(1)));
|
||||||
|
|
||||||
@ -1929,8 +1914,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
__ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
|
__ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
|
||||||
__ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
|
__ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
|
||||||
__ mov(r1, Operand(constant_elements));
|
__ mov(r1, Operand(constant_elements));
|
||||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||||
__ mov(r0, Operand(Smi::FromInt(flags)));
|
__ mov(r0, Operand(Smi::FromInt(expr->ComputeFlags())));
|
||||||
__ Push(r3, r2, r1, r0);
|
__ Push(r3, r2, r1, r0);
|
||||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||||
} else {
|
} else {
|
||||||
@ -1940,6 +1925,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
|
|
||||||
bool result_saved = false; // Is the result saved to the stack?
|
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
|
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||||
// them into the newly cloned array.
|
// them into the newly cloned array.
|
||||||
@ -1956,7 +1943,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
}
|
}
|
||||||
VisitForAccumulatorValue(subexpr);
|
VisitForAccumulatorValue(subexpr);
|
||||||
|
|
||||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
if (has_fast_elements) {
|
||||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||||
__ ldr(r6, MemOperand(sp, kPointerSize)); // Copy of array literal.
|
__ ldr(r6, MemOperand(sp, kPointerSize)); // Copy of array literal.
|
||||||
__ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
|
__ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
|
||||||
|
@ -1677,23 +1677,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
__ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset));
|
__ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset));
|
||||||
__ Mov(x2, Smi::FromInt(expr->literal_index()));
|
__ Mov(x2, Smi::FromInt(expr->literal_index()));
|
||||||
__ Mov(x1, Operand(constant_properties));
|
__ Mov(x1, Operand(constant_properties));
|
||||||
int flags = expr->fast_elements()
|
int flags = expr->ComputeFlags();
|
||||||
? ObjectLiteral::kFastElements
|
|
||||||
: ObjectLiteral::kNoFlags;
|
|
||||||
flags |= expr->has_function()
|
|
||||||
? ObjectLiteral::kHasFunction
|
|
||||||
: ObjectLiteral::kNoFlags;
|
|
||||||
__ Mov(x0, Smi::FromInt(flags));
|
__ Mov(x0, Smi::FromInt(flags));
|
||||||
int properties_count = constant_properties->length() / 2;
|
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||||
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) {
|
|
||||||
__ Push(x3, x2, x1, x0);
|
__ Push(x3, x2, x1, x0);
|
||||||
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
||||||
} else {
|
} else {
|
||||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
}
|
}
|
||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
@ -1885,18 +1875,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||||
|
|
||||||
expr->BuildConstantElements(isolate());
|
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();
|
Handle<FixedArray> constant_elements = expr->constant_elements();
|
||||||
DCHECK_EQ(2, constant_elements->length());
|
bool has_fast_elements =
|
||||||
ElementsKind constant_elements_kind =
|
IsFastObjectElementsKind(expr->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)));
|
|
||||||
|
|
||||||
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
||||||
if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
|
if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
|
||||||
@ -1909,8 +1890,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
__ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset));
|
__ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset));
|
||||||
__ Mov(x2, Smi::FromInt(expr->literal_index()));
|
__ Mov(x2, Smi::FromInt(expr->literal_index()));
|
||||||
__ Mov(x1, Operand(constant_elements));
|
__ Mov(x1, Operand(constant_elements));
|
||||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||||
__ Mov(x0, Smi::FromInt(flags));
|
__ Mov(x0, Smi::FromInt(expr->ComputeFlags()));
|
||||||
__ Push(x3, x2, x1, x0);
|
__ Push(x3, x2, x1, x0);
|
||||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||||
} else {
|
} else {
|
||||||
@ -1920,6 +1901,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
|
|
||||||
bool result_saved = false; // Is the result saved to the stack?
|
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
|
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||||
// them into the newly cloned array.
|
// them into the newly cloned array.
|
||||||
@ -1936,7 +1919,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
}
|
}
|
||||||
VisitForAccumulatorValue(subexpr);
|
VisitForAccumulatorValue(subexpr);
|
||||||
|
|
||||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
if (has_fast_elements) {
|
||||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||||
__ Peek(x6, kPointerSize); // Copy of array literal.
|
__ Peek(x6, kPointerSize); // Copy of array literal.
|
||||||
__ Ldr(x1, FieldMemOperand(x6, JSObject::kElementsOffset));
|
__ Ldr(x1, FieldMemOperand(x6, JSObject::kElementsOffset));
|
||||||
|
@ -368,6 +368,7 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
|
|||||||
constant_properties_ = constant_properties;
|
constant_properties_ = constant_properties;
|
||||||
fast_elements_ =
|
fast_elements_ =
|
||||||
(max_element_index <= 32) || ((2 * elements) >= max_element_index);
|
(max_element_index <= 32) || ((2 * elements) >= max_element_index);
|
||||||
|
has_elements_ = elements > 0;
|
||||||
set_is_simple(is_simple);
|
set_is_simple(is_simple);
|
||||||
set_depth(depth_acc);
|
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 {
|
Handle<FixedArray> constant_properties() const {
|
||||||
return constant_properties_;
|
return constant_properties_;
|
||||||
}
|
}
|
||||||
|
int properties_count() const { return constant_properties_->length() / 2; }
|
||||||
ZoneList<Property*>* properties() const { return properties_; }
|
ZoneList<Property*>* properties() const { return properties_; }
|
||||||
bool fast_elements() const { return fast_elements_; }
|
bool fast_elements() const { return fast_elements_; }
|
||||||
bool may_store_doubles() const { return may_store_doubles_; }
|
bool may_store_doubles() const { return may_store_doubles_; }
|
||||||
bool has_function() const { return has_function_; }
|
bool has_function() const { return has_function_; }
|
||||||
|
bool has_elements() const { return has_elements_; }
|
||||||
|
|
||||||
// Decide if a property should be in the object boilerplate.
|
// Decide if a property should be in the object boilerplate.
|
||||||
static bool IsBoilerplateProperty(Property* property);
|
static bool IsBoilerplateProperty(Property* property);
|
||||||
@ -1499,16 +1501,20 @@ class ObjectLiteral FINAL : public MaterializedLiteral {
|
|||||||
void CalculateEmitStore(Zone* zone);
|
void CalculateEmitStore(Zone* zone);
|
||||||
|
|
||||||
// Assemble bitfield of flags for the CreateObjectLiteral helper.
|
// Assemble bitfield of flags for the CreateObjectLiteral helper.
|
||||||
int ComputeFlags() const {
|
int ComputeFlags(bool disable_mementos = false) const {
|
||||||
int flags = fast_elements() ? kFastElements : kNoFlags;
|
int flags = fast_elements() ? kFastElements : kNoFlags;
|
||||||
flags |= has_function() ? kHasFunction : kNoFlags;
|
flags |= has_function() ? kHasFunction : kNoFlags;
|
||||||
|
if (disable_mementos) {
|
||||||
|
flags |= kDisableMementos;
|
||||||
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Flags {
|
enum Flags {
|
||||||
kNoFlags = 0,
|
kNoFlags = 0,
|
||||||
kFastElements = 1,
|
kFastElements = 1,
|
||||||
kHasFunction = 1 << 1
|
kHasFunction = 1 << 1,
|
||||||
|
kDisableMementos = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Accessors: public ZoneObject {
|
struct Accessors: public ZoneObject {
|
||||||
@ -1533,6 +1539,7 @@ class ObjectLiteral FINAL : public MaterializedLiteral {
|
|||||||
properties_(properties),
|
properties_(properties),
|
||||||
boilerplate_properties_(boilerplate_properties),
|
boilerplate_properties_(boilerplate_properties),
|
||||||
fast_elements_(false),
|
fast_elements_(false),
|
||||||
|
has_elements_(false),
|
||||||
may_store_doubles_(false),
|
may_store_doubles_(false),
|
||||||
has_function_(has_function) {}
|
has_function_(has_function) {}
|
||||||
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
|
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
|
||||||
@ -1543,6 +1550,7 @@ class ObjectLiteral FINAL : public MaterializedLiteral {
|
|||||||
ZoneList<Property*>* properties_;
|
ZoneList<Property*>* properties_;
|
||||||
int boilerplate_properties_;
|
int boilerplate_properties_;
|
||||||
bool fast_elements_;
|
bool fast_elements_;
|
||||||
|
bool has_elements_;
|
||||||
bool may_store_doubles_;
|
bool may_store_doubles_;
|
||||||
bool has_function_;
|
bool has_function_;
|
||||||
};
|
};
|
||||||
@ -1578,6 +1586,12 @@ class ArrayLiteral FINAL : public MaterializedLiteral {
|
|||||||
DECLARE_NODE_TYPE(ArrayLiteral)
|
DECLARE_NODE_TYPE(ArrayLiteral)
|
||||||
|
|
||||||
Handle<FixedArray> constant_elements() const { return constant_elements_; }
|
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_; }
|
ZoneList<Expression*>* values() const { return values_; }
|
||||||
|
|
||||||
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
|
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
|
||||||
@ -1593,9 +1607,11 @@ class ArrayLiteral FINAL : public MaterializedLiteral {
|
|||||||
void BuildConstantElements(Isolate* isolate);
|
void BuildConstantElements(Isolate* isolate);
|
||||||
|
|
||||||
// Assemble bitfield of flags for the CreateArrayLiteral helper.
|
// Assemble bitfield of flags for the CreateArrayLiteral helper.
|
||||||
int ComputeFlags() const {
|
int ComputeFlags(bool disable_mementos = false) const {
|
||||||
int flags = depth() == 1 ? kShallowElements : kNoFlags;
|
int flags = depth() == 1 ? kShallowElements : kNoFlags;
|
||||||
flags |= ArrayLiteral::kDisableMementos;
|
if (disable_mementos) {
|
||||||
|
flags |= kDisableMementos;
|
||||||
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1627,7 +1627,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
|
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
|
||||||
Node* literal_index = jsgraph()->Constant(expr->literal_index());
|
Node* literal_index = jsgraph()->Constant(expr->literal_index());
|
||||||
Node* constants = jsgraph()->Constant(expr->constant_properties());
|
Node* constants = jsgraph()->Constant(expr->constant_properties());
|
||||||
Node* flags = jsgraph()->Constant(expr->ComputeFlags());
|
Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
|
||||||
const Operator* op =
|
const Operator* op =
|
||||||
javascript()->CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
javascript()->CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
||||||
Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
|
Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
|
||||||
@ -1819,7 +1819,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
|
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
|
||||||
Node* literal_index = jsgraph()->Constant(expr->literal_index());
|
Node* literal_index = jsgraph()->Constant(expr->literal_index());
|
||||||
Node* constants = jsgraph()->Constant(expr->constant_elements());
|
Node* constants = jsgraph()->Constant(expr->constant_elements());
|
||||||
Node* flags = jsgraph()->Constant(expr->ComputeFlags());
|
Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
|
||||||
const Operator* op =
|
const Operator* op =
|
||||||
javascript()->CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
javascript()->CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||||
Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
|
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() {
|
void FullCodeGenerator::Initialize() {
|
||||||
InitializeAstVisitor(info_->isolate(), info_->zone());
|
InitializeAstVisitor(info_->isolate(), info_->zone());
|
||||||
// The generation of debug code must match between the snapshot code and the
|
// The generation of debug code must match between the snapshot code and the
|
||||||
|
@ -715,7 +715,7 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
loop_depth_--;
|
loop_depth_--;
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroAssembler* masm() { return masm_; }
|
MacroAssembler* masm() const { return masm_; }
|
||||||
|
|
||||||
class ExpressionContext;
|
class ExpressionContext;
|
||||||
const ExpressionContext* context() { return context_; }
|
const ExpressionContext* context() { return context_; }
|
||||||
@ -759,6 +759,9 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
void PopulateDeoptimizationData(Handle<Code> code);
|
void PopulateDeoptimizationData(Handle<Code> code);
|
||||||
void PopulateTypeFeedbackInfo(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_; }
|
Handle<HandlerTable> handler_table() { return handler_table_; }
|
||||||
|
|
||||||
struct BailoutEntry {
|
struct BailoutEntry {
|
||||||
|
@ -5552,19 +5552,13 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
Handle<FixedArray> closure_literals(closure->literals(), isolate());
|
Handle<FixedArray> closure_literals(closure->literals(), isolate());
|
||||||
Handle<FixedArray> constant_properties = expr->constant_properties();
|
Handle<FixedArray> constant_properties = expr->constant_properties();
|
||||||
int literal_index = expr->literal_index();
|
int literal_index = expr->literal_index();
|
||||||
int flags = expr->fast_elements()
|
int flags = expr->ComputeFlags(true);
|
||||||
? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
|
|
||||||
flags |= expr->has_function()
|
|
||||||
? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
|
|
||||||
|
|
||||||
Add<HPushArguments>(Add<HConstant>(closure_literals),
|
Add<HPushArguments>(Add<HConstant>(closure_literals),
|
||||||
Add<HConstant>(literal_index),
|
Add<HConstant>(literal_index),
|
||||||
Add<HConstant>(constant_properties),
|
Add<HConstant>(constant_properties),
|
||||||
Add<HConstant>(flags));
|
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;
|
Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
|
||||||
literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
|
literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
|
||||||
Runtime::FunctionForId(function_id),
|
Runtime::FunctionForId(function_id),
|
||||||
@ -5723,10 +5717,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
// pass an empty fixed array to the runtime function instead.
|
// pass an empty fixed array to the runtime function instead.
|
||||||
Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
|
Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
|
||||||
int literal_index = expr->literal_index();
|
int literal_index = expr->literal_index();
|
||||||
int flags = expr->depth() == 1
|
int flags = expr->ComputeFlags(true);
|
||||||
? ArrayLiteral::kShallowElements
|
|
||||||
: ArrayLiteral::kNoFlags;
|
|
||||||
flags |= ArrayLiteral::kDisableMementos;
|
|
||||||
|
|
||||||
Add<HPushArguments>(Add<HConstant>(literals),
|
Add<HPushArguments>(Add<HConstant>(literals),
|
||||||
Add<HConstant>(literal_index),
|
Add<HConstant>(literal_index),
|
||||||
|
@ -1622,17 +1622,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
|
|
||||||
expr->BuildConstantProperties(isolate());
|
expr->BuildConstantProperties(isolate());
|
||||||
Handle<FixedArray> constant_properties = expr->constant_properties();
|
Handle<FixedArray> constant_properties = expr->constant_properties();
|
||||||
int flags = expr->fast_elements()
|
int flags = expr->ComputeFlags();
|
||||||
? ObjectLiteral::kFastElements
|
// If any of the keys would store to the elements array, then we shouldn't
|
||||||
: ObjectLiteral::kNoFlags;
|
// allow it.
|
||||||
flags |= expr->has_function()
|
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||||
? 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) {
|
|
||||||
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||||
__ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
|
__ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
|
||||||
__ push(Immediate(Smi::FromInt(expr->literal_index())));
|
__ 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(ebx, Immediate(Smi::FromInt(expr->literal_index())));
|
||||||
__ mov(ecx, Immediate(constant_properties));
|
__ mov(ecx, Immediate(constant_properties));
|
||||||
__ mov(edx, Immediate(Smi::FromInt(flags)));
|
__ mov(edx, Immediate(Smi::FromInt(flags)));
|
||||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
}
|
}
|
||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
@ -1824,20 +1817,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||||
|
|
||||||
expr->BuildConstantElements(isolate());
|
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();
|
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 =
|
bool has_constant_fast_elements =
|
||||||
IsFastObjectElementsKind(constant_elements_kind);
|
IsFastObjectElementsKind(expr->constant_elements_kind());
|
||||||
Handle<FixedArrayBase> constant_elements_values(
|
|
||||||
FixedArrayBase::cast(constant_elements->get(1)));
|
|
||||||
|
|
||||||
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
||||||
if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
|
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;
|
allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||||
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||||
__ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
|
__ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
|
||||||
__ push(Immediate(Smi::FromInt(expr->literal_index())));
|
__ push(Immediate(Smi::FromInt(expr->literal_index())));
|
||||||
__ push(Immediate(constant_elements));
|
__ push(Immediate(constant_elements));
|
||||||
__ push(Immediate(Smi::FromInt(flags)));
|
__ push(Immediate(Smi::FromInt(expr->ComputeFlags())));
|
||||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||||
} else {
|
} else {
|
||||||
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||||
@ -1864,6 +1846,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
|
|
||||||
bool result_saved = false; // Is the result saved to the stack?
|
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
|
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||||
// them into the newly cloned array.
|
// them into the newly cloned array.
|
||||||
@ -1880,7 +1864,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
}
|
}
|
||||||
VisitForAccumulatorValue(subexpr);
|
VisitForAccumulatorValue(subexpr);
|
||||||
|
|
||||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
if (has_constant_fast_elements) {
|
||||||
// Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
|
// Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
|
||||||
// cannot transition and don't need to call the runtime stub.
|
// cannot transition and don't need to call the runtime stub.
|
||||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||||
|
@ -1684,21 +1684,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
__ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
|
__ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
|
||||||
__ li(a2, Operand(Smi::FromInt(expr->literal_index())));
|
__ li(a2, Operand(Smi::FromInt(expr->literal_index())));
|
||||||
__ li(a1, Operand(constant_properties));
|
__ li(a1, Operand(constant_properties));
|
||||||
int flags = expr->fast_elements()
|
__ li(a0, Operand(Smi::FromInt(expr->ComputeFlags())));
|
||||||
? ObjectLiteral::kFastElements
|
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||||
: 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) {
|
|
||||||
__ Push(a3, a2, a1, a0);
|
__ Push(a3, a2, a1, a0);
|
||||||
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
__ CallRuntime(Runtime::kCreateObjectLiteral, 4);
|
||||||
} else {
|
} else {
|
||||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
}
|
}
|
||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
@ -1890,21 +1881,10 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||||
|
|
||||||
expr->BuildConstantElements(isolate());
|
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();
|
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 =
|
bool has_fast_elements =
|
||||||
IsFastObjectElementsKind(constant_elements_kind);
|
IsFastObjectElementsKind(expr->constant_elements_kind());
|
||||||
Handle<FixedArrayBase> constant_elements_values(
|
|
||||||
FixedArrayBase::cast(constant_elements->get(1)));
|
|
||||||
|
|
||||||
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
||||||
if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
|
if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
|
||||||
@ -1918,8 +1898,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
__ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
|
__ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
|
||||||
__ li(a2, Operand(Smi::FromInt(expr->literal_index())));
|
__ li(a2, Operand(Smi::FromInt(expr->literal_index())));
|
||||||
__ li(a1, Operand(constant_elements));
|
__ li(a1, Operand(constant_elements));
|
||||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||||
__ li(a0, Operand(Smi::FromInt(flags)));
|
__ li(a0, Operand(Smi::FromInt(expr->ComputeFlags())));
|
||||||
__ Push(a3, a2, a1, a0);
|
__ Push(a3, a2, a1, a0);
|
||||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||||
} else {
|
} else {
|
||||||
@ -1929,6 +1909,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
|
|
||||||
bool result_saved = false; // Is the result saved to the stack?
|
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
|
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||||
// them into the newly cloned array.
|
// them into the newly cloned array.
|
||||||
@ -1946,7 +1928,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
|
|
||||||
VisitForAccumulatorValue(subexpr);
|
VisitForAccumulatorValue(subexpr);
|
||||||
|
|
||||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
if (has_fast_elements) {
|
||||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
||||||
__ lw(t2, MemOperand(sp, kPointerSize)); // Copy of array literal.
|
__ lw(t2, MemOperand(sp, kPointerSize)); // Copy of array literal.
|
||||||
__ lw(a1, FieldMemOperand(t2, JSObject::kElementsOffset));
|
__ lw(a1, FieldMemOperand(t2, JSObject::kElementsOffset));
|
||||||
|
@ -237,6 +237,7 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
|
|||||||
CONVERT_SMI_ARG_CHECKED(flags, 3);
|
CONVERT_SMI_ARG_CHECKED(flags, 3);
|
||||||
bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
|
bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
|
||||||
bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 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());
|
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);
|
Handle<JSObject>(JSObject::cast(site->transition_info()), isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
AllocationSiteUsageContext usage_context(isolate, site, true);
|
AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
|
||||||
usage_context.EnterNewScope();
|
usage_context.EnterNewScope();
|
||||||
MaybeHandle<Object> maybe_copy =
|
MaybeHandle<Object> maybe_copy =
|
||||||
JSObject::DeepCopy(boilerplate, &usage_context);
|
JSObject::DeepCopy(boilerplate, &usage_context);
|
||||||
|
@ -1657,16 +1657,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
|
|
||||||
expr->BuildConstantProperties(isolate());
|
expr->BuildConstantProperties(isolate());
|
||||||
Handle<FixedArray> constant_properties = expr->constant_properties();
|
Handle<FixedArray> constant_properties = expr->constant_properties();
|
||||||
int flags = expr->fast_elements()
|
int flags = expr->ComputeFlags();
|
||||||
? ObjectLiteral::kFastElements
|
if (MustCreateObjectLiteralWithRuntime(expr)) {
|
||||||
: 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) {
|
|
||||||
__ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
__ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||||
__ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
|
__ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
|
||||||
__ Push(Smi::FromInt(expr->literal_index()));
|
__ Push(Smi::FromInt(expr->literal_index()));
|
||||||
@ -1679,7 +1671,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
__ Move(rbx, Smi::FromInt(expr->literal_index()));
|
__ Move(rbx, Smi::FromInt(expr->literal_index()));
|
||||||
__ Move(rcx, constant_properties);
|
__ Move(rcx, constant_properties);
|
||||||
__ Move(rdx, Smi::FromInt(flags));
|
__ Move(rdx, Smi::FromInt(flags));
|
||||||
FastCloneShallowObjectStub stub(isolate(), properties_count);
|
FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
}
|
}
|
||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
@ -1858,20 +1850,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||||
|
|
||||||
expr->BuildConstantElements(isolate());
|
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();
|
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 =
|
bool has_constant_fast_elements =
|
||||||
IsFastObjectElementsKind(constant_elements_kind);
|
IsFastObjectElementsKind(expr->constant_elements_kind());
|
||||||
Handle<FixedArrayBase> constant_elements_values(
|
|
||||||
FixedArrayBase::cast(constant_elements->get(1)));
|
|
||||||
|
|
||||||
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
|
||||||
if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
|
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;
|
allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
|
if (MustCreateArrayLiteralWithRuntime(expr)) {
|
||||||
__ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
__ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||||
__ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
|
__ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
|
||||||
__ Push(Smi::FromInt(expr->literal_index()));
|
__ Push(Smi::FromInt(expr->literal_index()));
|
||||||
__ Push(constant_elements);
|
__ Push(constant_elements);
|
||||||
__ Push(Smi::FromInt(flags));
|
__ Push(Smi::FromInt(expr->ComputeFlags()));
|
||||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
|
||||||
} else {
|
} else {
|
||||||
__ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
__ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
||||||
@ -1898,6 +1879,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||||
|
|
||||||
bool result_saved = false; // Is the result saved to the stack?
|
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
|
// Emit code to evaluate all the non-constant subexpressions and to store
|
||||||
// them into the newly cloned array.
|
// them into the newly cloned array.
|
||||||
@ -1914,7 +1897,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
|||||||
}
|
}
|
||||||
VisitForAccumulatorValue(subexpr);
|
VisitForAccumulatorValue(subexpr);
|
||||||
|
|
||||||
if (IsFastObjectElementsKind(constant_elements_kind)) {
|
if (has_constant_fast_elements) {
|
||||||
// Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
|
// Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
|
||||||
// cannot transition and don't need to call the runtime stub.
|
// cannot transition and don't need to call the runtime stub.
|
||||||
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
|
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