Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Side by Side Diff: src/ast/ast.cc

Issue 2625873009: [ast] Remove heap accesses from AST numbering (Closed)
Patch Set: Address nits Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ast/ast.h ('k') | src/ast/ast-numbering.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/ast/ast.h" 5 #include "src/ast/ast.h"
6 6
7 #include <cmath> // For isfinite. 7 #include <cmath> // For isfinite.
8 8
9 #include "src/ast/compile-time-value.h" 9 #include "src/ast/compile-time-value.h"
10 #include "src/ast/prettyprinter.h" 10 #include "src/ast/prettyprinter.h"
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 return nullptr; 66 return nullptr;
67 } 67 }
68 } 68 }
69 69
70 #undef RETURN_NODE 70 #undef RETURN_NODE
71 71
72 bool Expression::IsSmiLiteral() const { 72 bool Expression::IsSmiLiteral() const {
73 return IsLiteral() && AsLiteral()->raw_value()->IsSmi(); 73 return IsLiteral() && AsLiteral()->raw_value()->IsSmi();
74 } 74 }
75 75
76 bool Expression::IsNumberLiteral() const {
77 return IsLiteral() && AsLiteral()->raw_value()->IsNumber();
78 }
79
76 bool Expression::IsStringLiteral() const { 80 bool Expression::IsStringLiteral() const {
77 return IsLiteral() && AsLiteral()->raw_value()->IsString(); 81 return IsLiteral() && AsLiteral()->raw_value()->IsString();
78 } 82 }
79 83
80 bool Expression::IsPropertyName() const { 84 bool Expression::IsPropertyName() const {
81 return IsLiteral() && AsLiteral()->IsPropertyName(); 85 return IsLiteral() && AsLiteral()->IsPropertyName();
82 } 86 }
83 87
84 bool Expression::IsNullLiteral() const { 88 bool Expression::IsNullLiteral() const {
85 if (!IsLiteral()) return false; 89 if (!IsLiteral()) return false;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 raw_name_ = copy_from->raw_name_; 197 raw_name_ = copy_from->raw_name_;
194 } 198 }
195 199
196 void VariableProxy::BindTo(Variable* var) { 200 void VariableProxy::BindTo(Variable* var) {
197 DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name()); 201 DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
198 set_var(var); 202 set_var(var);
199 set_is_resolved(); 203 set_is_resolved();
200 var->set_is_used(); 204 var->set_is_used();
201 } 205 }
202 206
203 207 void VariableProxy::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
204 void VariableProxy::AssignFeedbackVectorSlots(Isolate* isolate,
205 FeedbackVectorSpec* spec,
206 FeedbackVectorSlotCache* cache) { 208 FeedbackVectorSlotCache* cache) {
207 if (UsesVariableFeedbackSlot()) { 209 if (UsesVariableFeedbackSlot()) {
208 // VariableProxies that point to the same Variable within a function can 210 // VariableProxies that point to the same Variable within a function can
209 // make their loads from the same IC slot. 211 // make their loads from the same IC slot.
210 if (var()->IsUnallocated() || var()->mode() == DYNAMIC_GLOBAL) { 212 if (var()->IsUnallocated() || var()->mode() == DYNAMIC_GLOBAL) {
211 ZoneHashMap::Entry* entry = cache->Get(var()); 213 ZoneHashMap::Entry* entry = cache->Get(var());
212 if (entry != NULL) { 214 if (entry != NULL) {
213 variable_feedback_slot_ = FeedbackVectorSlot( 215 variable_feedback_slot_ = FeedbackVectorSlot(
214 static_cast<int>(reinterpret_cast<intptr_t>(entry->value))); 216 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)));
215 return; 217 return;
(...skipping 15 matching lines...) Expand all
231 expr->AsVariableProxy()->var()->IsUnallocated()) || 233 expr->AsVariableProxy()->var()->IsUnallocated()) ||
232 assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) { 234 assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) {
233 // TODO(ishell): consider using ICSlotCache for variables here. 235 // TODO(ishell): consider using ICSlotCache for variables here.
234 FeedbackVectorSlotKind kind = assign_type == KEYED_PROPERTY 236 FeedbackVectorSlotKind kind = assign_type == KEYED_PROPERTY
235 ? FeedbackVectorSlotKind::KEYED_STORE_IC 237 ? FeedbackVectorSlotKind::KEYED_STORE_IC
236 : FeedbackVectorSlotKind::STORE_IC; 238 : FeedbackVectorSlotKind::STORE_IC;
237 *out_slot = spec->AddSlot(kind); 239 *out_slot = spec->AddSlot(kind);
238 } 240 }
239 } 241 }
240 242
241 void ForInStatement::AssignFeedbackVectorSlots(Isolate* isolate, 243 void ForInStatement::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
242 FeedbackVectorSpec* spec,
243 FeedbackVectorSlotCache* cache) { 244 FeedbackVectorSlotCache* cache) {
244 AssignVectorSlots(each(), spec, &each_slot_); 245 AssignVectorSlots(each(), spec, &each_slot_);
245 for_in_feedback_slot_ = spec->AddGeneralSlot(); 246 for_in_feedback_slot_ = spec->AddGeneralSlot();
246 } 247 }
247 248
248 Assignment::Assignment(Token::Value op, Expression* target, Expression* value, 249 Assignment::Assignment(Token::Value op, Expression* target, Expression* value,
249 int pos) 250 int pos)
250 : Expression(pos, kAssignment), 251 : Expression(pos, kAssignment),
251 target_(target), 252 target_(target),
252 value_(value), 253 value_(value),
253 binary_operation_(NULL) { 254 binary_operation_(NULL) {
254 bit_field_ |= IsUninitializedField::encode(false) | 255 bit_field_ |= IsUninitializedField::encode(false) |
255 KeyTypeField::encode(ELEMENT) | 256 KeyTypeField::encode(ELEMENT) |
256 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op); 257 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op);
257 } 258 }
258 259
259 void Assignment::AssignFeedbackVectorSlots(Isolate* isolate, 260 void Assignment::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
260 FeedbackVectorSpec* spec,
261 FeedbackVectorSlotCache* cache) { 261 FeedbackVectorSlotCache* cache) {
262 AssignVectorSlots(target(), spec, &slot_); 262 AssignVectorSlots(target(), spec, &slot_);
263 } 263 }
264 264
265 265 void CountOperation::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
266 void CountOperation::AssignFeedbackVectorSlots(Isolate* isolate,
267 FeedbackVectorSpec* spec,
268 FeedbackVectorSlotCache* cache) { 266 FeedbackVectorSlotCache* cache) {
269 AssignVectorSlots(expression(), spec, &slot_); 267 AssignVectorSlots(expression(), spec, &slot_);
270 // Assign a slot to collect feedback about binary operations. Used only in 268 // Assign a slot to collect feedback about binary operations. Used only in
271 // ignition. Fullcodegen uses AstId to record type feedback. 269 // ignition. Fullcodegen uses AstId to record type feedback.
272 binary_operation_slot_ = spec->AddInterpreterBinaryOpICSlot(); 270 binary_operation_slot_ = spec->AddInterpreterBinaryOpICSlot();
273 } 271 }
274 272
275 273
276 Token::Value Assignment::binary_op() const { 274 Token::Value Assignment::binary_op() const {
277 switch (op()) { 275 switch (op()) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 IsConciseMethod(value_->AsFunctionLiteral()->kind()))); 364 IsConciseMethod(value_->AsFunctionLiteral()->kind())));
367 } 365 }
368 366
369 ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value, 367 ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
370 Kind kind, bool is_static, 368 Kind kind, bool is_static,
371 bool is_computed_name) 369 bool is_computed_name)
372 : LiteralProperty(key, value, is_computed_name), 370 : LiteralProperty(key, value, is_computed_name),
373 kind_(kind), 371 kind_(kind),
374 is_static_(is_static) {} 372 is_static_(is_static) {}
375 373
376 void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate, 374 void ClassLiteral::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
377 FeedbackVectorSpec* spec,
378 FeedbackVectorSlotCache* cache) { 375 FeedbackVectorSlotCache* cache) {
379 // This logic that computes the number of slots needed for vector store 376 // This logic that computes the number of slots needed for vector store
380 // ICs must mirror BytecodeGenerator::VisitClassLiteral. 377 // ICs must mirror BytecodeGenerator::VisitClassLiteral.
381 if (FunctionLiteral::NeedsHomeObject(constructor())) { 378 if (FunctionLiteral::NeedsHomeObject(constructor())) {
382 home_object_slot_ = spec->AddStoreICSlot(); 379 home_object_slot_ = spec->AddStoreICSlot();
383 } 380 }
384 381
385 if (NeedsProxySlot()) { 382 if (NeedsProxySlot()) {
386 proxy_slot_ = spec->AddStoreICSlot(); 383 proxy_slot_ = spec->AddStoreICSlot();
387 } 384 }
(...skipping 15 matching lines...) Expand all
403 CompileTimeValue::IsCompileTimeValue(value_)); 400 CompileTimeValue::IsCompileTimeValue(value_));
404 } 401 }
405 402
406 403
407 void ObjectLiteral::Property::set_emit_store(bool emit_store) { 404 void ObjectLiteral::Property::set_emit_store(bool emit_store) {
408 emit_store_ = emit_store; 405 emit_store_ = emit_store;
409 } 406 }
410 407
411 bool ObjectLiteral::Property::emit_store() const { return emit_store_; } 408 bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
412 409
413 void ObjectLiteral::AssignFeedbackVectorSlots(Isolate* isolate, 410 void ObjectLiteral::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
414 FeedbackVectorSpec* spec,
415 FeedbackVectorSlotCache* cache) { 411 FeedbackVectorSlotCache* cache) {
416 // This logic that computes the number of slots needed for vector store 412 // This logic that computes the number of slots needed for vector store
417 // ics must mirror FullCodeGenerator::VisitObjectLiteral. 413 // ics must mirror FullCodeGenerator::VisitObjectLiteral.
418 int property_index = 0; 414 int property_index = 0;
419 for (; property_index < properties()->length(); property_index++) { 415 for (; property_index < properties()->length(); property_index++) {
420 ObjectLiteral::Property* property = properties()->at(property_index); 416 ObjectLiteral::Property* property = properties()->at(property_index);
421 if (property->is_computed_name()) break; 417 if (property->is_computed_name()) break;
422 if (property->IsCompileTimeValue()) continue; 418 if (property->IsCompileTimeValue()) continue;
423 419
424 Literal* key = property->key()->AsLiteral(); 420 Literal* key = property->key()->AsLiteral();
425 Expression* value = property->value(); 421 Expression* value = property->value();
426 switch (property->kind()) { 422 switch (property->kind()) {
427 case ObjectLiteral::Property::SPREAD: 423 case ObjectLiteral::Property::SPREAD:
428 case ObjectLiteral::Property::CONSTANT: 424 case ObjectLiteral::Property::CONSTANT:
429 UNREACHABLE(); 425 UNREACHABLE();
430 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 426 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
431 // Fall through. 427 // Fall through.
432 case ObjectLiteral::Property::COMPUTED: 428 case ObjectLiteral::Property::COMPUTED:
433 // It is safe to use [[Put]] here because the boilerplate already 429 // It is safe to use [[Put]] here because the boilerplate already
434 // contains computed properties with an uninitialized value. 430 // contains computed properties with an uninitialized value.
435 if (key->value()->IsInternalizedString()) { 431 if (key->IsStringLiteral()) {
436 if (property->emit_store()) { 432 if (property->emit_store()) {
437 property->SetSlot(spec->AddStoreICSlot()); 433 property->SetSlot(spec->AddStoreICSlot());
438 if (FunctionLiteral::NeedsHomeObject(value)) { 434 if (FunctionLiteral::NeedsHomeObject(value)) {
439 property->SetSlot(spec->AddStoreICSlot(), 1); 435 property->SetSlot(spec->AddStoreICSlot(), 1);
440 } 436 }
441 } 437 }
442 break; 438 break;
443 } 439 }
444 if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) { 440 if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
445 property->SetSlot(spec->AddStoreICSlot()); 441 property->SetSlot(spec->AddStoreICSlot());
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 entry->value = property; 501 entry->value = property;
506 } 502 }
507 } 503 }
508 504
509 505
510 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) { 506 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
511 return property != NULL && 507 return property != NULL &&
512 property->kind() != ObjectLiteral::Property::PROTOTYPE; 508 property->kind() != ObjectLiteral::Property::PROTOTYPE;
513 } 509 }
514 510
515 511 void ObjectLiteral::InitDepthAndFlags() {
516 void ObjectLiteral::BuildConstantProperties(Isolate* isolate) { 512 if (depth_ > 0) return;
517 if (!constant_properties_.is_null()) return;
518
519 // Allocate a fixed array to hold all the constant properties.
520 Handle<FixedArray> constant_properties = isolate->factory()->NewFixedArray(
521 boilerplate_properties_ * 2, TENURED);
522 513
523 int position = 0; 514 int position = 0;
524 // Accumulate the value in local variables and store it at the end. 515 // Accumulate the value in local variables and store it at the end.
525 bool is_simple = true; 516 bool is_simple = true;
526 int depth_acc = 1; 517 int depth_acc = 1;
527 uint32_t max_element_index = 0; 518 uint32_t max_element_index = 0;
528 uint32_t elements = 0; 519 uint32_t elements = 0;
529 for (int i = 0; i < properties()->length(); i++) { 520 for (int i = 0; i < properties()->length(); i++) {
530 ObjectLiteral::Property* property = properties()->at(i); 521 ObjectLiteral::Property* property = properties()->at(i);
531 if (!IsBoilerplateProperty(property)) { 522 if (!IsBoilerplateProperty(property)) {
532 is_simple = false; 523 is_simple = false;
533 continue; 524 continue;
534 } 525 }
535 526
536 if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) { 527 if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
537 DCHECK(property->is_computed_name()); 528 DCHECK(property->is_computed_name());
538 is_simple = false; 529 is_simple = false;
539 break; 530 break;
540 } 531 }
541 DCHECK(!property->is_computed_name()); 532 DCHECK(!property->is_computed_name());
542 533
543 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral(); 534 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
544 if (m_literal != NULL) { 535 if (m_literal != NULL) {
545 m_literal->BuildConstants(isolate); 536 m_literal->InitDepthAndFlags();
546 if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1; 537 if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1;
547 } 538 }
548 539
549 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined 540 const AstValue* key = property->key()->AsLiteral()->raw_value();
550 // value for COMPUTED properties, the real value is filled in at 541 Expression* value = property->value();
551 // runtime. The enumeration order is maintained. 542
552 Handle<Object> key = property->key()->AsLiteral()->value(); 543 bool is_compile_time_value = CompileTimeValue::IsCompileTimeValue(value);
553 Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
554 544
555 // Ensure objects that may, at any point in time, contain fields with double 545 // Ensure objects that may, at any point in time, contain fields with double
556 // representation are always treated as nested objects. This is true for 546 // representation are always treated as nested objects. This is true for
557 // computed fields (value is undefined), and smi and double literals 547 // computed fields, and smi and double literals.
558 // (value->IsNumber()).
559 // TODO(verwaest): Remove once we can store them inline. 548 // TODO(verwaest): Remove once we can store them inline.
560 if (FLAG_track_double_fields && 549 if (FLAG_track_double_fields &&
561 (value->IsNumber() || value->IsUninitialized(isolate))) { 550 (value->IsNumberLiteral() || !is_compile_time_value)) {
562 bit_field_ = MayStoreDoublesField::update(bit_field_, true); 551 bit_field_ = MayStoreDoublesField::update(bit_field_, true);
563 } 552 }
564 553
565 is_simple = is_simple && !value->IsUninitialized(isolate); 554 is_simple = is_simple && is_compile_time_value;
566 555
567 // Keep track of the number of elements in the object literal and 556 // Keep track of the number of elements in the object literal and
568 // the largest element index. If the largest element index is 557 // the largest element index. If the largest element index is
569 // much larger than the number of elements, creating an object 558 // much larger than the number of elements, creating an object
570 // literal with fast elements will be a waste of space. 559 // literal with fast elements will be a waste of space.
571 uint32_t element_index = 0; 560 uint32_t element_index = 0;
572 if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) { 561 if (key->IsString() && key->AsString()->AsArrayIndex(&element_index)) {
573 max_element_index = Max(element_index, max_element_index); 562 max_element_index = Max(element_index, max_element_index);
574 elements++; 563 elements++;
575 key = isolate->factory()->NewNumberFromUint(element_index); 564 } else if (key->ToUint32(&element_index) && element_index != kMaxUInt32) {
576 } else if (key->ToArrayIndex(&element_index)) {
577 max_element_index = Max(element_index, max_element_index); 565 max_element_index = Max(element_index, max_element_index);
578 elements++; 566 elements++;
579 } else if (key->IsNumber()) {
580 key = isolate->factory()->NumberToString(key);
581 } 567 }
582 568
583 // Add name, value pair to the fixed array. 569 // Increment the position for the key and the value.
584 constant_properties->set(position++, *key); 570 position += 2;
585 constant_properties->set(position++, *value);
586 } 571 }
587 572
588 constant_properties_ = constant_properties;
589 bit_field_ = FastElementsField::update( 573 bit_field_ = FastElementsField::update(
590 bit_field_, 574 bit_field_,
591 (max_element_index <= 32) || ((2 * elements) >= max_element_index)); 575 (max_element_index <= 32) || ((2 * elements) >= max_element_index));
592 bit_field_ = HasElementsField::update(bit_field_, elements > 0); 576 bit_field_ = HasElementsField::update(bit_field_, elements > 0);
593 577
594 set_is_simple(is_simple); 578 set_is_simple(is_simple);
595 set_depth(depth_acc); 579 set_depth(depth_acc);
596 } 580 }
597 581
582 void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
583 if (!constant_properties_.is_null()) return;
584
585 // Allocate a fixed array to hold all the constant properties.
586 Handle<FixedArray> constant_properties =
587 isolate->factory()->NewFixedArray(boilerplate_properties_ * 2, TENURED);
588
589 int position = 0;
590 for (int i = 0; i < properties()->length(); i++) {
591 ObjectLiteral::Property* property = properties()->at(i);
592 if (!IsBoilerplateProperty(property)) {
593 continue;
594 }
595
596 if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
597 DCHECK(property->is_computed_name());
598 break;
599 }
600 DCHECK(!property->is_computed_name());
601
602 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
603 if (m_literal != NULL) {
604 m_literal->BuildConstants(isolate);
605 }
606
607 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
608 // value for COMPUTED properties, the real value is filled in at
609 // runtime. The enumeration order is maintained.
610 Handle<Object> key = property->key()->AsLiteral()->value();
611 Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
612
613 uint32_t element_index = 0;
614 if (key->IsString() && String::cast(*key)->AsArrayIndex(&element_index)) {
615 key = isolate->factory()->NewNumberFromUint(element_index);
616 } else if (key->IsNumber() && !key->ToArrayIndex(&element_index)) {
617 key = isolate->factory()->NumberToString(key);
618 }
619
620 // Add name, value pair to the fixed array.
621 constant_properties->set(position++, *key);
622 constant_properties->set(position++, *value);
623 }
624
625 constant_properties_ = constant_properties;
626 }
627
598 bool ObjectLiteral::IsFastCloningSupported() const { 628 bool ObjectLiteral::IsFastCloningSupported() const {
599 // The FastCloneShallowObject builtin doesn't copy elements, and object 629 // The FastCloneShallowObject builtin doesn't copy elements, and object
600 // literals don't support copy-on-write (COW) elements for now. 630 // literals don't support copy-on-write (COW) elements for now.
601 // TODO(mvstanton): make object literals support COW elements. 631 // TODO(mvstanton): make object literals support COW elements.
602 return fast_elements() && has_shallow_properties() && 632 return fast_elements() && has_shallow_properties() &&
603 properties_count() <= ConstructorBuiltinsAssembler:: 633 properties_count() <= ConstructorBuiltinsAssembler::
604 kMaximumClonedShallowObjectProperties; 634 kMaximumClonedShallowObjectProperties;
605 } 635 }
606 636
637 void ArrayLiteral::InitDepthAndFlags() {
638 DCHECK_LT(first_spread_index_, 0);
639
640 if (depth_ > 0) return;
641
642 int constants_length = values()->length();
643
644 // Fill in the literals.
645 bool is_simple = true;
646 int depth_acc = 1;
647 int array_index = 0;
648 for (; array_index < constants_length; array_index++) {
649 Expression* element = values()->at(array_index);
650 DCHECK(!element->IsSpread());
651 MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
652 if (m_literal != NULL) {
653 m_literal->InitDepthAndFlags();
654 if (m_literal->depth() + 1 > depth_acc) {
655 depth_acc = m_literal->depth() + 1;
656 }
657 }
658
659 if (!CompileTimeValue::IsCompileTimeValue(element)) {
660 is_simple = false;
661 }
662 }
663
664 set_is_simple(is_simple);
665 set_depth(depth_acc);
666 }
667
607 void ArrayLiteral::BuildConstantElements(Isolate* isolate) { 668 void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
608 DCHECK_LT(first_spread_index_, 0); 669 DCHECK_LT(first_spread_index_, 0);
609 670
610 if (!constant_elements_.is_null()) return; 671 if (!constant_elements_.is_null()) return;
611 672
612 int constants_length = values()->length(); 673 int constants_length = values()->length();
613 ElementsKind kind = FIRST_FAST_ELEMENTS_KIND; 674 ElementsKind kind = FIRST_FAST_ELEMENTS_KIND;
614 Handle<FixedArray> fixed_array = 675 Handle<FixedArray> fixed_array =
615 isolate->factory()->NewFixedArrayWithHoles(constants_length); 676 isolate->factory()->NewFixedArrayWithHoles(constants_length);
616 677
617 // Fill in the literals. 678 // Fill in the literals.
618 bool is_simple = true;
619 int depth_acc = 1;
620 bool is_holey = false; 679 bool is_holey = false;
621 int array_index = 0; 680 int array_index = 0;
622 for (; array_index < constants_length; array_index++) { 681 for (; array_index < constants_length; array_index++) {
623 Expression* element = values()->at(array_index); 682 Expression* element = values()->at(array_index);
624 DCHECK(!element->IsSpread()); 683 DCHECK(!element->IsSpread());
625 MaterializedLiteral* m_literal = element->AsMaterializedLiteral(); 684 MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
626 if (m_literal != NULL) { 685 if (m_literal != NULL) {
627 m_literal->BuildConstants(isolate); 686 m_literal->BuildConstants(isolate);
628 if (m_literal->depth() + 1 > depth_acc) {
629 depth_acc = m_literal->depth() + 1;
630 }
631 } 687 }
632 688
633 // New handle scope here, needs to be after BuildContants(). 689 // New handle scope here, needs to be after BuildContants().
634 HandleScope scope(isolate); 690 HandleScope scope(isolate);
635 Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate); 691 Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
636 if (boilerplate_value->IsTheHole(isolate)) { 692 if (boilerplate_value->IsTheHole(isolate)) {
637 is_holey = true; 693 is_holey = true;
638 continue; 694 continue;
639 } 695 }
640 696
641 if (boilerplate_value->IsUninitialized(isolate)) { 697 if (boilerplate_value->IsUninitialized(isolate)) {
642 boilerplate_value = handle(Smi::kZero, isolate); 698 boilerplate_value = handle(Smi::kZero, isolate);
643 is_simple = false;
644 } 699 }
645 700
646 kind = GetMoreGeneralElementsKind(kind, 701 kind = GetMoreGeneralElementsKind(kind,
647 boilerplate_value->OptimalElementsKind()); 702 boilerplate_value->OptimalElementsKind());
648 fixed_array->set(array_index, *boilerplate_value); 703 fixed_array->set(array_index, *boilerplate_value);
649 } 704 }
650 705
651 if (is_holey) kind = GetHoleyElementsKind(kind); 706 if (is_holey) kind = GetHoleyElementsKind(kind);
652 707
653 // Simple and shallow arrays can be lazily copied, we transform the 708 // Simple and shallow arrays can be lazily copied, we transform the
654 // elements array to a copy-on-write array. 709 // elements array to a copy-on-write array.
655 if (is_simple && depth_acc == 1 && array_index > 0 && 710 if (is_simple() && depth() == 1 && array_index > 0 &&
656 IsFastSmiOrObjectElementsKind(kind)) { 711 IsFastSmiOrObjectElementsKind(kind)) {
657 fixed_array->set_map(isolate->heap()->fixed_cow_array_map()); 712 fixed_array->set_map(isolate->heap()->fixed_cow_array_map());
658 } 713 }
659 714
660 Handle<FixedArrayBase> elements = fixed_array; 715 Handle<FixedArrayBase> elements = fixed_array;
661 if (IsFastDoubleElementsKind(kind)) { 716 if (IsFastDoubleElementsKind(kind)) {
662 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); 717 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
663 elements = isolate->factory()->NewFixedDoubleArray(constants_length); 718 elements = isolate->factory()->NewFixedDoubleArray(constants_length);
664 // We are copying from non-fast-double to fast-double. 719 // We are copying from non-fast-double to fast-double.
665 ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND; 720 ElementsKind from_kind = TERMINAL_FAST_ELEMENTS_KIND;
666 accessor->CopyElements(fixed_array, from_kind, elements, constants_length); 721 accessor->CopyElements(fixed_array, from_kind, elements, constants_length);
667 } 722 }
668 723
669 // Remember both the literal's constant values as well as the ElementsKind. 724 // Remember both the literal's constant values as well as the ElementsKind.
670 Handle<ConstantElementsPair> literals = 725 Handle<ConstantElementsPair> literals =
671 isolate->factory()->NewConstantElementsPair(kind, elements); 726 isolate->factory()->NewConstantElementsPair(kind, elements);
672 727
673 constant_elements_ = literals; 728 constant_elements_ = literals;
674 set_is_simple(is_simple);
675 set_depth(depth_acc);
676 } 729 }
677 730
678 bool ArrayLiteral::IsFastCloningSupported() const { 731 bool ArrayLiteral::IsFastCloningSupported() const {
679 return depth() <= 1 && 732 return depth() <= 1 &&
680 values()->length() <= 733 values()->length() <=
681 ConstructorBuiltinsAssembler::kMaximumClonedShallowArrayElements; 734 ConstructorBuiltinsAssembler::kMaximumClonedShallowArrayElements;
682 } 735 }
683 736
684 void ArrayLiteral::AssignFeedbackVectorSlots(Isolate* isolate, 737 void ArrayLiteral::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
685 FeedbackVectorSpec* spec,
686 FeedbackVectorSlotCache* cache) { 738 FeedbackVectorSlotCache* cache) {
687 // This logic that computes the number of slots needed for vector store 739 // This logic that computes the number of slots needed for vector store
688 // ics must mirror FullCodeGenerator::VisitArrayLiteral. 740 // ics must mirror FullCodeGenerator::VisitArrayLiteral.
689 for (int array_index = 0; array_index < values()->length(); array_index++) { 741 for (int array_index = 0; array_index < values()->length(); array_index++) {
690 Expression* subexpr = values()->at(array_index); 742 Expression* subexpr = values()->at(array_index);
691 DCHECK(!subexpr->IsSpread()); 743 DCHECK(!subexpr->IsSpread());
692 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 744 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
693 745
694 // We'll reuse the same literal slot for all of the non-constant 746 // We'll reuse the same literal slot for all of the non-constant
695 // subexpressions that use a keyed store IC. 747 // subexpressions that use a keyed store IC.
696 literal_slot_ = spec->AddKeyedStoreICSlot(); 748 literal_slot_ = spec->AddKeyedStoreICSlot();
697 return; 749 return;
698 } 750 }
699 } 751 }
700 752
701 753
702 Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression, 754 Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
703 Isolate* isolate) { 755 Isolate* isolate) {
704 if (expression->IsLiteral()) { 756 if (expression->IsLiteral()) {
705 return expression->AsLiteral()->value(); 757 return expression->AsLiteral()->value();
706 } 758 }
707 if (CompileTimeValue::IsCompileTimeValue(expression)) { 759 if (CompileTimeValue::IsCompileTimeValue(expression)) {
708 return CompileTimeValue::GetValue(isolate, expression); 760 return CompileTimeValue::GetValue(isolate, expression);
709 } 761 }
710 return isolate->factory()->uninitialized_value(); 762 return isolate->factory()->uninitialized_value();
711 } 763 }
712 764
765 void MaterializedLiteral::InitDepthAndFlags() {
766 if (IsArrayLiteral()) {
767 return AsArrayLiteral()->InitDepthAndFlags();
768 }
769 if (IsObjectLiteral()) {
770 return AsObjectLiteral()->InitDepthAndFlags();
771 }
772 DCHECK(IsRegExpLiteral());
773 DCHECK_LE(1, depth()); // Depth should be initialized.
774 }
713 775
714 void MaterializedLiteral::BuildConstants(Isolate* isolate) { 776 void MaterializedLiteral::BuildConstants(Isolate* isolate) {
715 if (IsArrayLiteral()) { 777 if (IsArrayLiteral()) {
716 return AsArrayLiteral()->BuildConstantElements(isolate); 778 return AsArrayLiteral()->BuildConstantElements(isolate);
717 } 779 }
718 if (IsObjectLiteral()) { 780 if (IsObjectLiteral()) {
719 return AsObjectLiteral()->BuildConstantProperties(isolate); 781 return AsObjectLiteral()->BuildConstantProperties(isolate);
720 } 782 }
721 DCHECK(IsRegExpLiteral()); 783 DCHECK(IsRegExpLiteral());
722 DCHECK(depth() >= 1); // Depth should be initialized.
723 } 784 }
724 785
725 786
726 void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { 787 void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
727 // TODO(olivf) If this Operation is used in a test context, then the 788 // TODO(olivf) If this Operation is used in a test context, then the
728 // expression has a ToBoolean stub and we want to collect the type 789 // expression has a ToBoolean stub and we want to collect the type
729 // information. However the GraphBuilder expects it to be on the instruction 790 // information. However the GraphBuilder expects it to be on the instruction
730 // corresponding to the TestContext, therefore we have to store it here and 791 // corresponding to the TestContext, therefore we have to store it here and
731 // not on the operand. 792 // not on the operand.
732 set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id())); 793 set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
733 } 794 }
734 795
735 796
736 void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { 797 void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
737 // TODO(olivf) If this Operation is used in a test context, then the right 798 // TODO(olivf) If this Operation is used in a test context, then the right
738 // hand side has a ToBoolean stub and we want to collect the type information. 799 // hand side has a ToBoolean stub and we want to collect the type information.
739 // However the GraphBuilder expects it to be on the instruction corresponding 800 // However the GraphBuilder expects it to be on the instruction corresponding
740 // to the TestContext, therefore we have to store it here and not on the 801 // to the TestContext, therefore we have to store it here and not on the
741 // right hand operand. 802 // right hand operand.
742 set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id())); 803 set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
743 } 804 }
744 805
745 void BinaryOperation::AssignFeedbackVectorSlots( 806 void BinaryOperation::AssignFeedbackVectorSlots(
746 Isolate* isolate, FeedbackVectorSpec* spec, 807 FeedbackVectorSpec* spec, FeedbackVectorSlotCache* cache) {
747 FeedbackVectorSlotCache* cache) {
748 // Feedback vector slot is only used by interpreter for binary operations. 808 // Feedback vector slot is only used by interpreter for binary operations.
749 // Full-codegen uses AstId to record type feedback. 809 // Full-codegen uses AstId to record type feedback.
750 switch (op()) { 810 switch (op()) {
751 // Comma, logical_or and logical_and do not collect type feedback. 811 // Comma, logical_or and logical_and do not collect type feedback.
752 case Token::COMMA: 812 case Token::COMMA:
753 case Token::AND: 813 case Token::AND:
754 case Token::OR: 814 case Token::OR:
755 return; 815 return;
756 default: 816 default:
757 type_feedback_slot_ = spec->AddInterpreterBinaryOpICSlot(); 817 type_feedback_slot_ = spec->AddInterpreterBinaryOpICSlot();
758 return; 818 return;
759 } 819 }
760 } 820 }
761 821
762 static bool IsTypeof(Expression* expr) { 822 static bool IsTypeof(Expression* expr) {
763 UnaryOperation* maybe_unary = expr->AsUnaryOperation(); 823 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
764 return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF; 824 return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
765 } 825 }
766 826
767 void CompareOperation::AssignFeedbackVectorSlots( 827 void CompareOperation::AssignFeedbackVectorSlots(
768 Isolate* isolate, FeedbackVectorSpec* spec, 828 FeedbackVectorSpec* spec, FeedbackVectorSlotCache* cache_) {
769 FeedbackVectorSlotCache* cache_) {
770 // Feedback vector slot is only used by interpreter for binary operations. 829 // Feedback vector slot is only used by interpreter for binary operations.
771 // Full-codegen uses AstId to record type feedback. 830 // Full-codegen uses AstId to record type feedback.
772 switch (op()) { 831 switch (op()) {
773 // instanceof and in do not collect type feedback. 832 // instanceof and in do not collect type feedback.
774 case Token::INSTANCEOF: 833 case Token::INSTANCEOF:
775 case Token::IN: 834 case Token::IN:
776 return; 835 return;
777 default: 836 default:
778 type_feedback_slot_ = spec->AddInterpreterCompareICSlot(); 837 type_feedback_slot_ = spec->AddInterpreterCompareICSlot();
779 } 838 }
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 return static_cast<const Node*>(this)->IsMonomorphic(); 976 return static_cast<const Node*>(this)->IsMonomorphic();
918 PROPERTY_NODE_LIST(GENERATE_CASE) 977 PROPERTY_NODE_LIST(GENERATE_CASE)
919 CALL_NODE_LIST(GENERATE_CASE) 978 CALL_NODE_LIST(GENERATE_CASE)
920 #undef GENERATE_CASE 979 #undef GENERATE_CASE
921 default: 980 default:
922 UNREACHABLE(); 981 UNREACHABLE();
923 return false; 982 return false;
924 } 983 }
925 } 984 }
926 985
927 void Call::AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec, 986 void Call::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
928 FeedbackVectorSlotCache* cache) { 987 FeedbackVectorSlotCache* cache) {
929 ic_slot_ = spec->AddCallICSlot(); 988 ic_slot_ = spec->AddCallICSlot();
930 } 989 }
931 990
932 Call::CallType Call::GetCallType() const { 991 Call::CallType Call::GetCallType() const {
933 VariableProxy* proxy = expression()->AsVariableProxy(); 992 VariableProxy* proxy = expression()->AsVariableProxy();
934 if (proxy != NULL) { 993 if (proxy != NULL) {
935 if (proxy->var()->IsUnallocated()) { 994 if (proxy->var()->IsUnallocated()) {
936 return GLOBAL_CALL; 995 return GLOBAL_CALL;
937 } else if (proxy->var()->IsLookupSlot()) { 996 } else if (proxy->var()->IsLookupSlot()) {
(...skipping 18 matching lines...) Expand all
956 return OTHER_CALL; 1015 return OTHER_CALL;
957 } 1016 }
958 1017
959 CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements, 1018 CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
960 int pos) 1019 int pos)
961 : Expression(pos, kCaseClause), 1020 : Expression(pos, kCaseClause),
962 label_(label), 1021 label_(label),
963 statements_(statements), 1022 statements_(statements),
964 compare_type_(AstType::None()) {} 1023 compare_type_(AstType::None()) {}
965 1024
966 void CaseClause::AssignFeedbackVectorSlots(Isolate* isolate, 1025 void CaseClause::AssignFeedbackVectorSlots(FeedbackVectorSpec* spec,
967 FeedbackVectorSpec* spec,
968 FeedbackVectorSlotCache* cache) { 1026 FeedbackVectorSlotCache* cache) {
969 type_feedback_slot_ = spec->AddInterpreterCompareICSlot(); 1027 type_feedback_slot_ = spec->AddInterpreterCompareICSlot();
970 } 1028 }
971 1029
972 uint32_t Literal::Hash() { 1030 uint32_t Literal::Hash() {
973 return raw_value()->IsString() 1031 return raw_value()->IsString()
974 ? raw_value()->AsString()->hash() 1032 ? raw_value()->AsString()->hash()
975 : ComputeLongHash(double_to_uint64(raw_value()->AsNumber())); 1033 : ComputeLongHash(double_to_uint64(raw_value()->AsNumber()));
976 } 1034 }
977 1035
978 1036
979 // static 1037 // static
980 bool Literal::Match(void* literal1, void* literal2) { 1038 bool Literal::Match(void* literal1, void* literal2) {
981 const AstValue* x = static_cast<Literal*>(literal1)->raw_value(); 1039 const AstValue* x = static_cast<Literal*>(literal1)->raw_value();
982 const AstValue* y = static_cast<Literal*>(literal2)->raw_value(); 1040 const AstValue* y = static_cast<Literal*>(literal2)->raw_value();
983 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) || 1041 return (x->IsString() && y->IsString() && x->AsString() == y->AsString()) ||
984 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber()); 1042 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
985 } 1043 }
986 1044
987 } // namespace internal 1045 } // namespace internal
988 } // namespace v8 1046 } // namespace v8
OLDNEW
« no previous file with comments | « src/ast/ast.h ('k') | src/ast/ast-numbering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698