Index: src/ast/ast.cc |
diff --git a/src/ast/ast.cc b/src/ast/ast.cc |
index f31b5d142ebc28772d6c4d03ec1f145d0f717194..c63f90ecf11f398ebfdecf5c6fd25356dd934f83 100644 |
--- a/src/ast/ast.cc |
+++ b/src/ast/ast.cc |
@@ -73,6 +73,10 @@ bool Expression::IsSmiLiteral() const { |
return IsLiteral() && AsLiteral()->raw_value()->IsSmi(); |
} |
+bool Expression::IsNumberLiteral() const { |
+ return IsLiteral() && AsLiteral()->raw_value()->IsNumber(); |
+} |
+ |
bool Expression::IsStringLiteral() const { |
return IsLiteral() && AsLiteral()->raw_value()->IsString(); |
} |
@@ -200,9 +204,7 @@ void VariableProxy::BindTo(Variable* var) { |
var->set_is_used(); |
} |
- |
-void VariableProxy::AssignFeedbackVectorSlots(Isolate* isolate, |
- FeedbackVectorSpec* spec, |
+void VariableProxy::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
if (UsesVariableFeedbackSlot()) { |
// VariableProxies that point to the same Variable within a function can |
@@ -238,8 +240,7 @@ static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec, |
} |
} |
-void ForInStatement::AssignFeedbackVectorSlots(Isolate* isolate, |
- FeedbackVectorSpec* spec, |
+void ForInStatement::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
AssignVectorSlots(each(), spec, &each_slot_); |
for_in_feedback_slot_ = spec->AddGeneralSlot(); |
@@ -256,15 +257,12 @@ Assignment::Assignment(Token::Value op, Expression* target, Expression* value, |
StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op); |
} |
-void Assignment::AssignFeedbackVectorSlots(Isolate* isolate, |
- FeedbackVectorSpec* spec, |
+void Assignment::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
AssignVectorSlots(target(), spec, &slot_); |
} |
- |
-void CountOperation::AssignFeedbackVectorSlots(Isolate* isolate, |
- FeedbackVectorSpec* spec, |
+void CountOperation::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
AssignVectorSlots(expression(), spec, &slot_); |
// Assign a slot to collect feedback about binary operations. Used only in |
@@ -373,8 +371,7 @@ ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value, |
kind_(kind), |
is_static_(is_static) {} |
-void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
- FeedbackVectorSpec* spec, |
+void ClassLiteral::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
// This logic that computes the number of slots needed for vector store |
// ICs must mirror BytecodeGenerator::VisitClassLiteral. |
@@ -410,8 +407,7 @@ void ObjectLiteral::Property::set_emit_store(bool emit_store) { |
bool ObjectLiteral::Property::emit_store() const { return emit_store_; } |
-void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
- FeedbackVectorSpec* spec, |
+void ObjectLiteral::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
// This logic that computes the number of slots needed for vector store |
// ics must mirror FullCodeGenerator::VisitObjectLiteral. |
@@ -432,7 +428,7 @@ void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
case ObjectLiteral::Property::COMPUTED: |
// It is safe to use [[Put]] here because the boilerplate already |
// contains computed properties with an uninitialized value. |
- if (key->value()->IsInternalizedString()) { |
+ if (key->IsStringLiteral()) { |
if (property->emit_store()) { |
property->SetSlot(spec->AddStoreICSlot()); |
if (FunctionLiteral::NeedsHomeObject(value)) { |
@@ -512,13 +508,8 @@ bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) { |
property->kind() != ObjectLiteral::Property::PROTOTYPE; |
} |
- |
-void ObjectLiteral::BuildConstantProperties(Isolate* isolate) { |
- if (!constant_properties_.is_null()) return; |
- |
- // Allocate a fixed array to hold all the constant properties. |
- Handle<FixedArray> constant_properties = isolate->factory()->NewFixedArray( |
- boilerplate_properties_ * 2, TENURED); |
+void ObjectLiteral::InitDepthAndFlags() { |
+ if (depth_ > 0) return; |
int position = 0; |
// Accumulate the value in local variables and store it at the end. |
@@ -542,50 +533,43 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) { |
MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral(); |
if (m_literal != NULL) { |
- m_literal->BuildConstants(isolate); |
+ m_literal->InitDepthAndFlags(); |
if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1; |
} |
- // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined |
- // value for COMPUTED properties, the real value is filled in at |
- // runtime. The enumeration order is maintained. |
- Handle<Object> key = property->key()->AsLiteral()->value(); |
- Handle<Object> value = GetBoilerplateValue(property->value(), isolate); |
+ const AstValue* key = property->key()->AsLiteral()->raw_value(); |
+ Expression* value = property->value(); |
+ |
+ bool is_compile_time_value = CompileTimeValue::IsCompileTimeValue(value); |
// Ensure objects that may, at any point in time, contain fields with double |
// representation are always treated as nested objects. This is true for |
- // computed fields (value is undefined), and smi and double literals |
- // (value->IsNumber()). |
+ // computed fields, and smi and double literals. |
// TODO(verwaest): Remove once we can store them inline. |
if (FLAG_track_double_fields && |
- (value->IsNumber() || value->IsUninitialized(isolate))) { |
+ (value->IsNumberLiteral() || !is_compile_time_value)) { |
bit_field_ = MayStoreDoublesField::update(bit_field_, true); |
} |
- is_simple = is_simple && !value->IsUninitialized(isolate); |
+ is_simple = is_simple && is_compile_time_value; |
// Keep track of the number of elements in the object literal and |
// the largest element index. If the largest element index is |
// much larger than the number of elements, creating an object |
// literal with fast elements will be a waste of space. |
uint32_t element_index = 0; |
- if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) { |
+ if (key->IsString() && key->AsString()->AsArrayIndex(&element_index)) { |
max_element_index = Max(element_index, max_element_index); |
elements++; |
- key = isolate->factory()->NewNumberFromUint(element_index); |
- } else if (key->ToArrayIndex(&element_index)) { |
+ } else if (key->ToUint32(&element_index) && element_index != kMaxUInt32) { |
max_element_index = Max(element_index, max_element_index); |
elements++; |
- } else if (key->IsNumber()) { |
- key = isolate->factory()->NumberToString(key); |
} |
- // Add name, value pair to the fixed array. |
- constant_properties->set(position++, *key); |
- constant_properties->set(position++, *value); |
+ // Increment the position for the key and the value. |
+ position += 2; |
} |
- constant_properties_ = constant_properties; |
bit_field_ = FastElementsField::update( |
bit_field_, |
(max_element_index <= 32) || ((2 * elements) >= max_element_index)); |
@@ -595,6 +579,52 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) { |
set_depth(depth_acc); |
} |
+void ObjectLiteral::BuildConstantProperties(Isolate* isolate) { |
+ if (!constant_properties_.is_null()) return; |
+ |
+ // Allocate a fixed array to hold all the constant properties. |
+ Handle<FixedArray> constant_properties = |
+ isolate->factory()->NewFixedArray(boilerplate_properties_ * 2, TENURED); |
+ |
+ int position = 0; |
+ for (int i = 0; i < properties()->length(); i++) { |
+ ObjectLiteral::Property* property = properties()->at(i); |
+ if (!IsBoilerplateProperty(property)) { |
+ continue; |
+ } |
+ |
+ if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) { |
+ DCHECK(property->is_computed_name()); |
+ break; |
+ } |
+ DCHECK(!property->is_computed_name()); |
+ |
+ MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral(); |
+ if (m_literal != NULL) { |
+ m_literal->BuildConstants(isolate); |
+ } |
+ |
+ // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined |
+ // value for COMPUTED properties, the real value is filled in at |
+ // runtime. The enumeration order is maintained. |
+ Handle<Object> key = property->key()->AsLiteral()->value(); |
+ Handle<Object> value = GetBoilerplateValue(property->value(), isolate); |
+ |
+ uint32_t element_index = 0; |
+ if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) { |
+ key = isolate->factory()->NewNumberFromUint(element_index); |
+ } else if (key->IsNumber() && !key->ToArrayIndex(&element_index)) { |
+ key = isolate->factory()->NumberToString(key); |
+ } |
+ |
+ // Add name, value pair to the fixed array. |
+ constant_properties->set(position++, *key); |
+ constant_properties->set(position++, *value); |
+ } |
+ |
+ constant_properties_ = constant_properties; |
+} |
+ |
bool ObjectLiteral::IsFastCloningSupported() const { |
// The FastCloneShallowObject builtin doesn't copy elements, and object |
// literals don't support copy-on-write (COW) elements for now. |
@@ -604,6 +634,37 @@ bool ObjectLiteral::IsFastCloningSupported() const { |
kMaximumClonedShallowObjectProperties; |
} |
+void ArrayLiteral::InitDepthAndFlags() { |
+ DCHECK_LT(first_spread_index_, 0); |
+ |
+ if (depth_ > 0) return; |
+ |
+ int constants_length = values()->length(); |
+ |
+ // Fill in the literals. |
+ bool is_simple = true; |
+ int depth_acc = 1; |
+ int array_index = 0; |
+ for (; array_index < constants_length; array_index++) { |
+ Expression* element = values()->at(array_index); |
+ DCHECK(!element->IsSpread()); |
+ MaterializedLiteral* m_literal = element->AsMaterializedLiteral(); |
+ if (m_literal != NULL) { |
+ m_literal->InitDepthAndFlags(); |
+ if (m_literal->depth() + 1 > depth_acc) { |
+ depth_acc = m_literal->depth() + 1; |
+ } |
+ } |
+ |
+ if (!CompileTimeValue::IsCompileTimeValue(element)) { |
+ is_simple = false; |
+ } |
+ } |
+ |
+ set_is_simple(is_simple); |
+ set_depth(depth_acc); |
+} |
+ |
void ArrayLiteral::BuildConstantElements(Isolate* isolate) { |
DCHECK_LT(first_spread_index_, 0); |
@@ -615,8 +676,6 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) { |
isolate->factory()->NewFixedArrayWithHoles(constants_length); |
// Fill in the literals. |
- bool is_simple = true; |
- int depth_acc = 1; |
bool is_holey = false; |
int array_index = 0; |
for (; array_index < constants_length; array_index++) { |
@@ -625,9 +684,6 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) { |
MaterializedLiteral* m_literal = element->AsMaterializedLiteral(); |
if (m_literal != NULL) { |
m_literal->BuildConstants(isolate); |
- if (m_literal->depth() + 1 > depth_acc) { |
- depth_acc = m_literal->depth() + 1; |
- } |
} |
// New handle scope here, needs to be after BuildContants(). |
@@ -640,7 +696,6 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) { |
if (boilerplate_value->IsUninitialized(isolate)) { |
boilerplate_value = handle(Smi::kZero, isolate); |
- is_simple = false; |
} |
kind = GetMoreGeneralElementsKind(kind, |
@@ -652,7 +707,7 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) { |
// Simple and shallow arrays can be lazily copied, we transform the |
// elements array to a copy-on-write array. |
- if (is_simple && depth_acc == 1 && array_index > 0 && |
+ if (is_simple() && depth() == 1 && array_index > 0 && |
IsFastSmiOrObjectElementsKind(kind)) { |
fixed_array->set_map(isolate->heap()->fixed_cow_array_map()); |
} |
@@ -671,8 +726,6 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) { |
isolate->factory()->NewConstantElementsPair(kind, elements); |
constant_elements_ = literals; |
- set_is_simple(is_simple); |
- set_depth(depth_acc); |
} |
bool ArrayLiteral::IsFastCloningSupported() const { |
@@ -681,8 +734,7 @@ bool ArrayLiteral::IsFastCloningSupported() const { |
ConstructorBuiltinsAssembler::kMaximumClonedShallowArrayElements; |
} |
-void ArrayLiteral::AssignFeedbackVectorSlots(Isolate* isolate, |
- FeedbackVectorSpec* spec, |
+void ArrayLiteral::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
// This logic that computes the number of slots needed for vector store |
// ics must mirror FullCodeGenerator::VisitArrayLiteral. |
@@ -710,6 +762,16 @@ Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression, |
return isolate->factory()->uninitialized_value(); |
} |
+void MaterializedLiteral::InitDepthAndFlags() { |
+ if (IsArrayLiteral()) { |
+ return AsArrayLiteral()->InitDepthAndFlags(); |
+ } |
+ if (IsObjectLiteral()) { |
+ return AsObjectLiteral()->InitDepthAndFlags(); |
+ } |
+ DCHECK(IsRegExpLiteral()); |
+ DCHECK_LE(1, depth()); // Depth should be initialized. |
+} |
void MaterializedLiteral::BuildConstants(Isolate* isolate) { |
if (IsArrayLiteral()) { |
@@ -719,7 +781,6 @@ void MaterializedLiteral::BuildConstants(Isolate* isolate) { |
return AsObjectLiteral()->BuildConstantProperties(isolate); |
} |
DCHECK(IsRegExpLiteral()); |
- DCHECK(depth() >= 1); // Depth should be initialized. |
} |
@@ -743,8 +804,7 @@ void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { |
} |
void BinaryOperation::AssignFeedbackVectorSlots( |
- Isolate* isolate, FeedbackVectorSpec* spec, |
- FeedbackVectorSlotCache* cache) { |
+ FeedbackVectorSpec* spec, FeedbackVectorSlotCache* cache) { |
// Feedback vector slot is only used by interpreter for binary operations. |
// Full-codegen uses AstId to record type feedback. |
switch (op()) { |
@@ -765,8 +825,7 @@ static bool IsTypeof(Expression* expr) { |
} |
void CompareOperation::AssignFeedbackVectorSlots( |
- Isolate* isolate, FeedbackVectorSpec* spec, |
- FeedbackVectorSlotCache* cache_) { |
+ FeedbackVectorSpec* spec, FeedbackVectorSlotCache* cache_) { |
// Feedback vector slot is only used by interpreter for binary operations. |
// Full-codegen uses AstId to record type feedback. |
switch (op()) { |
@@ -924,7 +983,7 @@ bool Expression::IsMonomorphic() const { |
} |
} |
-void Call::AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, |
+void Call::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
ic_slot_ = spec->AddCallICSlot(); |
} |
@@ -963,8 +1022,7 @@ CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements, |
statements_(statements), |
compare_type_(AstType::None()) {} |
-void CaseClause::AssignFeedbackVectorSlots(Isolate* isolate, |
- FeedbackVectorSpec* spec, |
+void CaseClause::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec, |
FeedbackVectorSlotCache* cache) { |
type_feedback_slot_ = spec->AddInterpreterCompareICSlot(); |
} |