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