Chromium Code Reviews| Index: src/ast/ast.cc |
| diff --git a/src/ast/ast.cc b/src/ast/ast.cc |
| index f31b5d142ebc28772d6c4d03ec1f145d0f717194..7f17e8c71d60a5b801c7194a3502155c0f5d7a9b 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(depth() >= 1); // Depth should be initialized. |
|
Toon Verwaest
2017/01/16 09:30:54
DCHECK_LE(1, depth());
Leszek Swirski
2017/01/16 12:01:11
Done.
|
| +} |
| 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(); |
| } |