| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 merge_block_(NULL) { | 704 merge_block_(NULL) { |
| 705 continuation->Continue(&first_true_block_, | 705 continuation->Continue(&first_true_block_, |
| 706 &first_false_block_, | 706 &first_false_block_, |
| 707 &position_); | 707 &position_); |
| 708 } | 708 } |
| 709 | 709 |
| 710 | 710 |
| 711 HInstruction* HGraphBuilder::IfBuilder::IfCompare( | 711 HInstruction* HGraphBuilder::IfBuilder::IfCompare( |
| 712 HValue* left, | 712 HValue* left, |
| 713 HValue* right, | 713 HValue* right, |
| 714 Token::Value token, | 714 Token::Value token) { |
| 715 Representation input_representation) { | |
| 716 HCompareIDAndBranch* compare = | 715 HCompareIDAndBranch* compare = |
| 717 new(zone()) HCompareIDAndBranch(left, right, token); | 716 new(zone()) HCompareIDAndBranch(left, right, token); |
| 718 compare->set_observed_input_representation(input_representation, | |
| 719 input_representation); | |
| 720 compare->AssumeRepresentation(input_representation); | |
| 721 AddCompare(compare); | 717 AddCompare(compare); |
| 722 return compare; | 718 return compare; |
| 723 } | 719 } |
| 724 | 720 |
| 725 | 721 |
| 726 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, | 722 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, |
| 727 Handle<Map> map) { | 723 Handle<Map> map) { |
| 728 HCompareMap* compare = | 724 HCompareMap* compare = |
| 729 new(zone()) HCompareMap(left, map, first_true_block_, first_false_block_); | 725 new(zone()) HCompareMap(left, map, first_true_block_, first_false_block_); |
| 730 AddCompare(compare); | 726 AddCompare(compare); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 builder_->set_current_block(exit_block_); | 958 builder_->set_current_block(exit_block_); |
| 963 // Pop the phi from the expression stack | 959 // Pop the phi from the expression stack |
| 964 builder_->environment()->Pop(); | 960 builder_->environment()->Pop(); |
| 965 finished_ = true; | 961 finished_ = true; |
| 966 } | 962 } |
| 967 | 963 |
| 968 | 964 |
| 969 HGraph* HGraphBuilder::CreateGraph() { | 965 HGraph* HGraphBuilder::CreateGraph() { |
| 970 graph_ = new(zone()) HGraph(info_); | 966 graph_ = new(zone()) HGraph(info_); |
| 971 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); | 967 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); |
| 972 HPhase phase("H_Block building", isolate()); | 968 HPhase phase("H_Block building", isolate(), zone()); |
| 973 set_current_block(graph()->entry_block()); | 969 set_current_block(graph()->entry_block()); |
| 974 if (!BuildGraph()) return NULL; | 970 if (!BuildGraph()) return NULL; |
| 975 graph()->FinalizeUniqueValueIds(); | 971 graph()->FinalizeUniqueValueIds(); |
| 976 return graph_; | 972 return graph_; |
| 977 } | 973 } |
| 978 | 974 |
| 979 | 975 |
| 980 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 976 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 981 ASSERT(current_block() != NULL); | 977 ASSERT(current_block() != NULL); |
| 982 current_block()->AddInstruction(instr); | 978 current_block()->AddInstruction(instr); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 999 HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(index, length); | 995 HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(index, length); |
| 1000 AddInstruction(result); | 996 AddInstruction(result); |
| 1001 return result; | 997 return result; |
| 1002 } | 998 } |
| 1003 | 999 |
| 1004 | 1000 |
| 1005 HReturn* HGraphBuilder::AddReturn(HValue* value) { | 1001 HReturn* HGraphBuilder::AddReturn(HValue* value) { |
| 1006 HValue* context = environment()->LookupContext(); | 1002 HValue* context = environment()->LookupContext(); |
| 1007 int num_parameters = graph()->info()->num_parameters(); | 1003 int num_parameters = graph()->info()->num_parameters(); |
| 1008 HValue* params = AddInstruction(new(graph()->zone()) | 1004 HValue* params = AddInstruction(new(graph()->zone()) |
| 1009 HConstant(num_parameters, Representation::Integer32())); | 1005 HConstant(num_parameters)); |
| 1010 HReturn* return_instruction = new(graph()->zone()) | 1006 HReturn* return_instruction = new(graph()->zone()) |
| 1011 HReturn(value, context, params); | 1007 HReturn(value, context, params); |
| 1012 current_block()->FinishExit(return_instruction); | 1008 current_block()->FinishExit(return_instruction); |
| 1013 return return_instruction; | 1009 return return_instruction; |
| 1014 } | 1010 } |
| 1015 | 1011 |
| 1016 | 1012 |
| 1017 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 1013 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
| 1018 HBasicBlock* b = graph()->CreateBasicBlock(); | 1014 HBasicBlock* b = graph()->CreateBasicBlock(); |
| 1019 b->SetInitialEnvironment(env); | 1015 b->SetInitialEnvironment(env); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 | 1160 |
| 1165 environment()->Push(new_elements); | 1161 environment()->Push(new_elements); |
| 1166 capacity_checker.Else(); | 1162 capacity_checker.Else(); |
| 1167 | 1163 |
| 1168 environment()->Push(elements); | 1164 environment()->Push(elements); |
| 1169 capacity_checker.End(); | 1165 capacity_checker.End(); |
| 1170 | 1166 |
| 1171 if (is_js_array) { | 1167 if (is_js_array) { |
| 1172 HValue* new_length = AddInstruction( | 1168 HValue* new_length = AddInstruction( |
| 1173 HAdd::New(zone, context, length, graph_->GetConstant1())); | 1169 HAdd::New(zone, context, length, graph_->GetConstant1())); |
| 1174 new_length->AssumeRepresentation(Representation::Integer32()); | |
| 1175 new_length->ClearFlag(HValue::kCanOverflow); | 1170 new_length->ClearFlag(HValue::kCanOverflow); |
| 1176 | 1171 |
| 1177 Representation representation = IsFastElementsKind(kind) | 1172 Representation representation = IsFastElementsKind(kind) |
| 1178 ? Representation::Smi() : Representation::Tagged(); | 1173 ? Representation::Smi() : Representation::Tagged(); |
| 1179 AddStore(object, HObjectAccess::ForArrayLength(), new_length, | 1174 AddStore(object, HObjectAccess::ForArrayLength(), new_length, |
| 1180 representation); | 1175 representation); |
| 1181 } | 1176 } |
| 1182 | 1177 |
| 1183 length_checker.Else(); | 1178 length_checker.Else(); |
| 1184 | 1179 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 } | 1332 } |
| 1338 | 1333 |
| 1339 | 1334 |
| 1340 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, | 1335 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, |
| 1341 ElementsKind kind, | 1336 ElementsKind kind, |
| 1342 HValue* capacity) { | 1337 HValue* capacity) { |
| 1343 Zone* zone = this->zone(); | 1338 Zone* zone = this->zone(); |
| 1344 | 1339 |
| 1345 int elements_size = IsFastDoubleElementsKind(kind) | 1340 int elements_size = IsFastDoubleElementsKind(kind) |
| 1346 ? kDoubleSize : kPointerSize; | 1341 ? kDoubleSize : kPointerSize; |
| 1347 HConstant* elements_size_value = | 1342 HConstant* elements_size_value = new(zone) HConstant(elements_size); |
| 1348 new(zone) HConstant(elements_size, Representation::Integer32()); | |
| 1349 AddInstruction(elements_size_value); | 1343 AddInstruction(elements_size_value); |
| 1350 HValue* mul = AddInstruction( | 1344 HValue* mul = AddInstruction( |
| 1351 HMul::New(zone, context, capacity, elements_size_value)); | 1345 HMul::New(zone, context, capacity, elements_size_value)); |
| 1352 mul->AssumeRepresentation(Representation::Integer32()); | |
| 1353 mul->ClearFlag(HValue::kCanOverflow); | 1346 mul->ClearFlag(HValue::kCanOverflow); |
| 1354 | 1347 |
| 1355 HConstant* header_size = | 1348 HConstant* header_size = new(zone) HConstant(FixedArray::kHeaderSize); |
| 1356 new(zone) HConstant(FixedArray::kHeaderSize, Representation::Integer32()); | |
| 1357 AddInstruction(header_size); | 1349 AddInstruction(header_size); |
| 1358 HValue* total_size = AddInstruction( | 1350 HValue* total_size = AddInstruction( |
| 1359 HAdd::New(zone, context, mul, header_size)); | 1351 HAdd::New(zone, context, mul, header_size)); |
| 1360 total_size->AssumeRepresentation(Representation::Integer32()); | |
| 1361 total_size->ClearFlag(HValue::kCanOverflow); | 1352 total_size->ClearFlag(HValue::kCanOverflow); |
| 1362 | 1353 |
| 1363 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); | 1354 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); |
| 1364 if (isolate()->heap()->ShouldGloballyPretenure()) { | 1355 if (isolate()->heap()->ShouldGloballyPretenure()) { |
| 1365 // TODO(hpayer): When pretenuring can be internalized, flags can become | 1356 // TODO(hpayer): When pretenuring can be internalized, flags can become |
| 1366 // private to HAllocate. | 1357 // private to HAllocate. |
| 1367 if (IsFastDoubleElementsKind(kind)) { | 1358 if (IsFastDoubleElementsKind(kind)) { |
| 1368 flags = static_cast<HAllocate::Flags>( | 1359 flags = static_cast<HAllocate::Flags>( |
| 1369 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); | 1360 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); |
| 1370 } else { | 1361 } else { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1408 | 1399 |
| 1409 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1400 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
| 1410 HValue* array_map, | 1401 HValue* array_map, |
| 1411 AllocationSiteMode mode, | 1402 AllocationSiteMode mode, |
| 1412 HValue* allocation_site_payload, | 1403 HValue* allocation_site_payload, |
| 1413 HValue* length_field) { | 1404 HValue* length_field) { |
| 1414 | 1405 |
| 1415 AddStore(array, HObjectAccess::ForMap(), array_map); | 1406 AddStore(array, HObjectAccess::ForMap(), array_map); |
| 1416 | 1407 |
| 1417 HConstant* empty_fixed_array = | 1408 HConstant* empty_fixed_array = |
| 1418 new(zone()) HConstant( | 1409 new(zone()) HConstant(isolate()->factory()->empty_fixed_array()); |
| 1419 Handle<FixedArray>(isolate()->heap()->empty_fixed_array()), | |
| 1420 Representation::Tagged()); | |
| 1421 AddInstruction(empty_fixed_array); | 1410 AddInstruction(empty_fixed_array); |
| 1422 | 1411 |
| 1423 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 1412 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 1424 AddStore(array, access, empty_fixed_array); | 1413 AddStore(array, access, empty_fixed_array); |
| 1425 AddStore(array, HObjectAccess::ForArrayLength(), length_field); | 1414 AddStore(array, HObjectAccess::ForArrayLength(), length_field); |
| 1426 | 1415 |
| 1427 if (mode == TRACK_ALLOCATION_SITE) { | 1416 if (mode == TRACK_ALLOCATION_SITE) { |
| 1428 BuildCreateAllocationSiteInfo(array, | 1417 BuildCreateAllocationSiteInfo(array, |
| 1429 JSArray::kSize, | 1418 JSArray::kSize, |
| 1430 allocation_site_payload); | 1419 allocation_site_payload); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1449 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); | 1438 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); |
| 1450 } | 1439 } |
| 1451 | 1440 |
| 1452 | 1441 |
| 1453 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1442 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
| 1454 HValue* old_capacity) { | 1443 HValue* old_capacity) { |
| 1455 Zone* zone = this->zone(); | 1444 Zone* zone = this->zone(); |
| 1456 HValue* half_old_capacity = | 1445 HValue* half_old_capacity = |
| 1457 AddInstruction(HShr::New(zone, context, old_capacity, | 1446 AddInstruction(HShr::New(zone, context, old_capacity, |
| 1458 graph_->GetConstant1())); | 1447 graph_->GetConstant1())); |
| 1459 half_old_capacity->AssumeRepresentation(Representation::Integer32()); | |
| 1460 half_old_capacity->ClearFlag(HValue::kCanOverflow); | 1448 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
| 1461 | 1449 |
| 1462 HValue* new_capacity = AddInstruction( | 1450 HValue* new_capacity = AddInstruction( |
| 1463 HAdd::New(zone, context, half_old_capacity, old_capacity)); | 1451 HAdd::New(zone, context, half_old_capacity, old_capacity)); |
| 1464 new_capacity->AssumeRepresentation(Representation::Integer32()); | |
| 1465 new_capacity->ClearFlag(HValue::kCanOverflow); | 1452 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 1466 | 1453 |
| 1467 HValue* min_growth = | 1454 HValue* min_growth = AddInstruction(new(zone) HConstant(16)); |
| 1468 AddInstruction(new(zone) HConstant(16, Representation::Integer32())); | |
| 1469 | 1455 |
| 1470 new_capacity = AddInstruction( | 1456 new_capacity = AddInstruction( |
| 1471 HAdd::New(zone, context, new_capacity, min_growth)); | 1457 HAdd::New(zone, context, new_capacity, min_growth)); |
| 1472 new_capacity->AssumeRepresentation(Representation::Integer32()); | |
| 1473 new_capacity->ClearFlag(HValue::kCanOverflow); | 1458 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 1474 | 1459 |
| 1475 return new_capacity; | 1460 return new_capacity; |
| 1476 } | 1461 } |
| 1477 | 1462 |
| 1478 | 1463 |
| 1479 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { | 1464 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { |
| 1480 Zone* zone = this->zone(); | 1465 Zone* zone = this->zone(); |
| 1481 Heap* heap = isolate()->heap(); | 1466 Heap* heap = isolate()->heap(); |
| 1482 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize | 1467 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1518 ElementsKind elements_kind, | 1503 ElementsKind elements_kind, |
| 1519 HValue* from, | 1504 HValue* from, |
| 1520 HValue* to) { | 1505 HValue* to) { |
| 1521 // Fast elements kinds need to be initialized in case statements below cause | 1506 // Fast elements kinds need to be initialized in case statements below cause |
| 1522 // a garbage collection. | 1507 // a garbage collection. |
| 1523 Factory* factory = isolate()->factory(); | 1508 Factory* factory = isolate()->factory(); |
| 1524 | 1509 |
| 1525 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 1510 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 1526 Zone* zone = this->zone(); | 1511 Zone* zone = this->zone(); |
| 1527 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 1512 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
| 1528 ? AddInstruction(new(zone) HConstant(factory->the_hole_value(), | 1513 ? AddInstruction(new(zone) HConstant(factory->the_hole_value())) |
| 1529 Representation::Tagged())) | 1514 : AddInstruction(new(zone) HConstant(nan_double)); |
| 1530 : AddInstruction(new(zone) HConstant(nan_double, | |
| 1531 Representation::Double())); | |
| 1532 | 1515 |
| 1533 // Special loop unfolding case | 1516 // Special loop unfolding case |
| 1534 static const int kLoopUnfoldLimit = 4; | 1517 static const int kLoopUnfoldLimit = 4; |
| 1535 bool unfold_loop = false; | 1518 bool unfold_loop = false; |
| 1536 int initial_capacity = JSArray::kPreallocatedArrayElements; | 1519 int initial_capacity = JSArray::kPreallocatedArrayElements; |
| 1537 if (from->IsConstant() && to->IsConstant() && | 1520 if (from->IsConstant() && to->IsConstant() && |
| 1538 initial_capacity <= kLoopUnfoldLimit) { | 1521 initial_capacity <= kLoopUnfoldLimit) { |
| 1539 HConstant* constant_from = HConstant::cast(from); | 1522 HConstant* constant_from = HConstant::cast(from); |
| 1540 HConstant* constant_to = HConstant::cast(to); | 1523 HConstant* constant_to = HConstant::cast(to); |
| 1541 | 1524 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 int elems_offset = size; | 1617 int elems_offset = size; |
| 1635 if (length > 0) { | 1618 if (length > 0) { |
| 1636 size += IsFastDoubleElementsKind(kind) | 1619 size += IsFastDoubleElementsKind(kind) |
| 1637 ? FixedDoubleArray::SizeFor(length) | 1620 ? FixedDoubleArray::SizeFor(length) |
| 1638 : FixedArray::SizeFor(length); | 1621 : FixedArray::SizeFor(length); |
| 1639 } | 1622 } |
| 1640 | 1623 |
| 1641 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); | 1624 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); |
| 1642 // Allocate both the JS array and the elements array in one big | 1625 // Allocate both the JS array and the elements array in one big |
| 1643 // allocation. This avoids multiple limit checks. | 1626 // allocation. This avoids multiple limit checks. |
| 1644 HValue* size_in_bytes = | 1627 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(size)); |
| 1645 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); | |
| 1646 HInstruction* object = | 1628 HInstruction* object = |
| 1647 AddInstruction(new(zone) HAllocate(context, | 1629 AddInstruction(new(zone) HAllocate(context, |
| 1648 size_in_bytes, | 1630 size_in_bytes, |
| 1649 HType::JSObject(), | 1631 HType::JSObject(), |
| 1650 allocate_flags)); | 1632 allocate_flags)); |
| 1651 | 1633 |
| 1652 // Copy the JS array part. | 1634 // Copy the JS array part. |
| 1653 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 1635 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 1654 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 1636 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 1655 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 1637 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1693 kind)); | 1675 kind)); |
| 1694 } | 1676 } |
| 1695 } | 1677 } |
| 1696 | 1678 |
| 1697 return object; | 1679 return object; |
| 1698 } | 1680 } |
| 1699 | 1681 |
| 1700 | 1682 |
| 1701 void HGraphBuilder::BuildCompareNil( | 1683 void HGraphBuilder::BuildCompareNil( |
| 1702 HValue* value, | 1684 HValue* value, |
| 1703 CompareNilICStub::Types types, | 1685 Handle<Type> type, |
| 1704 Handle<Map> map, | |
| 1705 int position, | 1686 int position, |
| 1706 HIfContinuation* continuation) { | 1687 HIfContinuation* continuation) { |
| 1707 IfBuilder if_nil(this, position); | 1688 IfBuilder if_nil(this, position); |
| 1708 bool needs_or = false; | 1689 bool needs_or = false; |
| 1709 if (types.Contains(CompareNilICStub::NULL_TYPE)) { | 1690 if (type->Maybe(Type::Null())) { |
| 1710 if (needs_or) if_nil.Or(); | 1691 if (needs_or) if_nil.Or(); |
| 1711 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); | 1692 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
| 1712 needs_or = true; | 1693 needs_or = true; |
| 1713 } | 1694 } |
| 1714 if (types.Contains(CompareNilICStub::UNDEFINED)) { | 1695 if (type->Maybe(Type::Undefined())) { |
| 1715 if (needs_or) if_nil.Or(); | 1696 if (needs_or) if_nil.Or(); |
| 1716 if_nil.If<HCompareObjectEqAndBranch>(value, | 1697 if_nil.If<HCompareObjectEqAndBranch>(value, |
| 1717 graph()->GetConstantUndefined()); | 1698 graph()->GetConstantUndefined()); |
| 1718 needs_or = true; | 1699 needs_or = true; |
| 1719 } | 1700 } |
| 1720 // Handle either undetectable or monomorphic, not both. | 1701 if (type->Maybe(Type::Undetectable())) { |
| 1721 ASSERT(!types.Contains(CompareNilICStub::UNDETECTABLE) || | |
| 1722 !types.Contains(CompareNilICStub::MONOMORPHIC_MAP)); | |
| 1723 if (types.Contains(CompareNilICStub::UNDETECTABLE)) { | |
| 1724 if (needs_or) if_nil.Or(); | 1702 if (needs_or) if_nil.Or(); |
| 1725 if_nil.If<HIsUndetectableAndBranch>(value); | 1703 if_nil.If<HIsUndetectableAndBranch>(value); |
| 1726 } else { | 1704 } else { |
| 1727 if_nil.Then(); | 1705 if_nil.Then(); |
| 1728 if_nil.Else(); | 1706 if_nil.Else(); |
| 1729 if (!map.is_null() && types.Contains(CompareNilICStub::MONOMORPHIC_MAP)) { | 1707 if (type->NumClasses() == 1) { |
| 1730 BuildCheckNonSmi(value); | 1708 BuildCheckNonSmi(value); |
| 1731 // For ICs, the map checked below is a sentinel map that gets replaced by | 1709 // For ICs, the map checked below is a sentinel map that gets replaced by |
| 1732 // the monomorphic map when the code is used as a template to generate a | 1710 // the monomorphic map when the code is used as a template to generate a |
| 1733 // new IC. For optimized functions, there is no sentinel map, the map | 1711 // new IC. For optimized functions, there is no sentinel map, the map |
| 1734 // emitted below is the actual monomorphic map. | 1712 // emitted below is the actual monomorphic map. |
| 1735 BuildCheckMap(value, map); | 1713 BuildCheckMap(value, type->Classes().Current()); |
| 1736 } else { | 1714 } else { |
| 1737 if_nil.Deopt(); | 1715 if_nil.Deopt(); |
| 1738 } | 1716 } |
| 1739 } | 1717 } |
| 1740 | 1718 |
| 1741 if_nil.CaptureContinuation(continuation); | 1719 if_nil.CaptureContinuation(continuation); |
| 1742 } | 1720 } |
| 1743 | 1721 |
| 1744 | 1722 |
| 1745 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, | 1723 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1762 HGlobalObject(context)); | 1740 HGlobalObject(context)); |
| 1763 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 1741 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 1764 GlobalObject::kNativeContextOffset); | 1742 GlobalObject::kNativeContextOffset); |
| 1765 return AddLoad(global_object, access); | 1743 return AddLoad(global_object, access); |
| 1766 } | 1744 } |
| 1767 | 1745 |
| 1768 | 1746 |
| 1769 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { | 1747 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { |
| 1770 HInstruction* native_context = BuildGetNativeContext(context); | 1748 HInstruction* native_context = BuildGetNativeContext(context); |
| 1771 HInstruction* index = AddInstruction(new(zone()) | 1749 HInstruction* index = AddInstruction(new(zone()) |
| 1772 HConstant(Context::ARRAY_FUNCTION_INDEX, Representation::Integer32())); | 1750 HConstant(Context::ARRAY_FUNCTION_INDEX)); |
| 1773 | 1751 |
| 1774 return AddInstruction(new (zone()) | 1752 return AddInstruction(new (zone()) |
| 1775 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS)); | 1753 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS)); |
| 1776 } | 1754 } |
| 1777 | 1755 |
| 1778 | 1756 |
| 1779 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 1757 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
| 1780 ElementsKind kind, | 1758 ElementsKind kind, |
| 1781 HValue* allocation_site_payload, | 1759 HValue* allocation_site_payload, |
| 1782 bool disable_allocation_sites) : | 1760 bool disable_allocation_sites) : |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1798 mode_(DONT_TRACK_ALLOCATION_SITE), | 1776 mode_(DONT_TRACK_ALLOCATION_SITE), |
| 1799 allocation_site_payload_(NULL), | 1777 allocation_site_payload_(NULL), |
| 1800 constructor_function_(constructor_function) { | 1778 constructor_function_(constructor_function) { |
| 1801 } | 1779 } |
| 1802 | 1780 |
| 1803 | 1781 |
| 1804 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1782 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { |
| 1805 HInstruction* native_context = builder()->BuildGetNativeContext(context); | 1783 HInstruction* native_context = builder()->BuildGetNativeContext(context); |
| 1806 | 1784 |
| 1807 HInstruction* index = builder()->AddInstruction(new(zone()) | 1785 HInstruction* index = builder()->AddInstruction(new(zone()) |
| 1808 HConstant(Context::JS_ARRAY_MAPS_INDEX, Representation::Integer32())); | 1786 HConstant(Context::JS_ARRAY_MAPS_INDEX)); |
| 1809 | 1787 |
| 1810 HInstruction* map_array = builder()->AddInstruction(new(zone()) | 1788 HInstruction* map_array = builder()->AddInstruction(new(zone()) |
| 1811 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS)); | 1789 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS)); |
| 1812 | 1790 |
| 1813 HInstruction* kind_index = builder()->AddInstruction(new(zone()) | 1791 HInstruction* kind_index = builder()->AddInstruction(new(zone()) |
| 1814 HConstant(kind_, Representation::Integer32())); | 1792 HConstant(kind_)); |
| 1815 | 1793 |
| 1816 return builder()->AddInstruction(new(zone()) | 1794 return builder()->AddInstruction(new(zone()) |
| 1817 HLoadKeyed(map_array, kind_index, NULL, FAST_ELEMENTS)); | 1795 HLoadKeyed(map_array, kind_index, NULL, FAST_ELEMENTS)); |
| 1818 } | 1796 } |
| 1819 | 1797 |
| 1820 | 1798 |
| 1821 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1799 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
| 1822 // Find the map near the constructor function | 1800 // Find the map near the constructor function |
| 1823 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1801 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1824 return AddInstruction( | 1802 return AddInstruction( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1837 if (mode_ == TRACK_ALLOCATION_SITE) { | 1815 if (mode_ == TRACK_ALLOCATION_SITE) { |
| 1838 base_size += AllocationSiteInfo::kSize; | 1816 base_size += AllocationSiteInfo::kSize; |
| 1839 } | 1817 } |
| 1840 | 1818 |
| 1841 if (IsFastDoubleElementsKind(kind_)) { | 1819 if (IsFastDoubleElementsKind(kind_)) { |
| 1842 base_size += FixedDoubleArray::kHeaderSize; | 1820 base_size += FixedDoubleArray::kHeaderSize; |
| 1843 } else { | 1821 } else { |
| 1844 base_size += FixedArray::kHeaderSize; | 1822 base_size += FixedArray::kHeaderSize; |
| 1845 } | 1823 } |
| 1846 | 1824 |
| 1847 HInstruction* elements_size_value = new(zone()) | 1825 HInstruction* elements_size_value = new(zone()) HConstant(elements_size()); |
| 1848 HConstant(elements_size(), Representation::Integer32()); | |
| 1849 AddInstruction(elements_size_value); | 1826 AddInstruction(elements_size_value); |
| 1850 HInstruction* mul = HMul::New(zone(), context, length_node, | 1827 HInstruction* mul = HMul::New(zone(), context, length_node, |
| 1851 elements_size_value); | 1828 elements_size_value); |
| 1852 mul->AssumeRepresentation(Representation::Integer32()); | |
| 1853 mul->ClearFlag(HValue::kCanOverflow); | 1829 mul->ClearFlag(HValue::kCanOverflow); |
| 1854 AddInstruction(mul); | 1830 AddInstruction(mul); |
| 1855 | 1831 |
| 1856 HInstruction* base = new(zone()) HConstant(base_size, | 1832 HInstruction* base = new(zone()) HConstant(base_size); |
| 1857 Representation::Integer32()); | |
| 1858 AddInstruction(base); | 1833 AddInstruction(base); |
| 1859 HInstruction* total_size = HAdd::New(zone(), context, base, mul); | 1834 HInstruction* total_size = HAdd::New(zone(), context, base, mul); |
| 1860 total_size->AssumeRepresentation(Representation::Integer32()); | |
| 1861 total_size->ClearFlag(HValue::kCanOverflow); | 1835 total_size->ClearFlag(HValue::kCanOverflow); |
| 1862 AddInstruction(total_size); | 1836 AddInstruction(total_size); |
| 1863 return total_size; | 1837 return total_size; |
| 1864 } | 1838 } |
| 1865 | 1839 |
| 1866 | 1840 |
| 1867 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | 1841 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { |
| 1868 int base_size = JSArray::kSize; | 1842 int base_size = JSArray::kSize; |
| 1869 if (mode_ == TRACK_ALLOCATION_SITE) { | 1843 if (mode_ == TRACK_ALLOCATION_SITE) { |
| 1870 base_size += AllocationSiteInfo::kSize; | 1844 base_size += AllocationSiteInfo::kSize; |
| 1871 } | 1845 } |
| 1872 | 1846 |
| 1873 base_size += IsFastDoubleElementsKind(kind_) | 1847 base_size += IsFastDoubleElementsKind(kind_) |
| 1874 ? FixedDoubleArray::SizeFor(initial_capacity()) | 1848 ? FixedDoubleArray::SizeFor(initial_capacity()) |
| 1875 : FixedArray::SizeFor(initial_capacity()); | 1849 : FixedArray::SizeFor(initial_capacity()); |
| 1876 | 1850 |
| 1877 HConstant* array_size = | 1851 HConstant* array_size = new(zone()) HConstant(base_size); |
| 1878 new(zone()) HConstant(base_size, Representation::Integer32()); | |
| 1879 AddInstruction(array_size); | 1852 AddInstruction(array_size); |
| 1880 return array_size; | 1853 return array_size; |
| 1881 } | 1854 } |
| 1882 | 1855 |
| 1883 | 1856 |
| 1884 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { | 1857 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { |
| 1885 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); | 1858 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); |
| 1886 HConstant* capacity = | 1859 HConstant* capacity = new(zone()) HConstant(initial_capacity()); |
| 1887 new(zone()) HConstant(initial_capacity(), Representation::Integer32()); | |
| 1888 AddInstruction(capacity); | 1860 AddInstruction(capacity); |
| 1889 return AllocateArray(size_in_bytes, | 1861 return AllocateArray(size_in_bytes, |
| 1890 capacity, | 1862 capacity, |
| 1891 builder()->graph()->GetConstant0(), | 1863 builder()->graph()->GetConstant0(), |
| 1892 true); | 1864 true); |
| 1893 } | 1865 } |
| 1894 | 1866 |
| 1895 | 1867 |
| 1896 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, | 1868 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, |
| 1897 HValue* length_field, | 1869 HValue* length_field, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1955 Representation representation) { | 1927 Representation representation) { |
| 1956 HLoadNamedField *instr = | 1928 HLoadNamedField *instr = |
| 1957 new(zone()) HLoadNamedField(object, access, typecheck, representation); | 1929 new(zone()) HLoadNamedField(object, access, typecheck, representation); |
| 1958 AddInstruction(instr); | 1930 AddInstruction(instr); |
| 1959 return instr; | 1931 return instr; |
| 1960 } | 1932 } |
| 1961 | 1933 |
| 1962 | 1934 |
| 1963 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 1935 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
| 1964 Handle<Map> map) { | 1936 Handle<Map> map) { |
| 1965 HValue* constant = | 1937 HValue* constant = AddInstruction(new(zone()) HConstant(map)); |
| 1966 AddInstruction(new(zone()) HConstant(map, Representation::Tagged())); | |
| 1967 HStoreNamedField *instr = | 1938 HStoreNamedField *instr = |
| 1968 new(zone()) HStoreNamedField(object, HObjectAccess::ForMap(), constant); | 1939 new(zone()) HStoreNamedField(object, HObjectAccess::ForMap(), constant); |
| 1969 AddInstruction(instr); | 1940 AddInstruction(instr); |
| 1970 return instr; | 1941 return instr; |
| 1971 } | 1942 } |
| 1972 | 1943 |
| 1973 | 1944 |
| 1974 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) | 1945 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) |
| 1975 : HGraphBuilder(info), | 1946 : HGraphBuilder(info), |
| 1976 function_state_(NULL), | 1947 function_state_(NULL), |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2408 HLoopInformation* loop_; | 2379 HLoopInformation* loop_; |
| 2409 HBasicBlock* block_; | 2380 HBasicBlock* block_; |
| 2410 HBasicBlock* loop_header_; | 2381 HBasicBlock* loop_header_; |
| 2411 int loop_index; | 2382 int loop_index; |
| 2412 int loop_length; | 2383 int loop_length; |
| 2413 HSuccessorIterator successor_iterator; | 2384 HSuccessorIterator successor_iterator; |
| 2414 }; | 2385 }; |
| 2415 | 2386 |
| 2416 | 2387 |
| 2417 void HGraph::OrderBlocks() { | 2388 void HGraph::OrderBlocks() { |
| 2418 HPhase phase("H_Block ordering", isolate()); | 2389 HPhase phase("H_Block ordering", isolate(), zone()); |
| 2419 BitVector visited(blocks_.length(), zone()); | 2390 BitVector visited(blocks_.length(), zone()); |
| 2420 | 2391 |
| 2421 ZoneList<HBasicBlock*> reverse_result(8, zone()); | 2392 ZoneList<HBasicBlock*> reverse_result(8, zone()); |
| 2422 HBasicBlock* start = blocks_[0]; | 2393 HBasicBlock* start = blocks_[0]; |
| 2423 PostorderProcessor* postorder = | 2394 PostorderProcessor* postorder = |
| 2424 PostorderProcessor::CreateEntryProcessor(zone(), start, &visited); | 2395 PostorderProcessor::CreateEntryProcessor(zone(), start, &visited); |
| 2425 while (postorder != NULL) { | 2396 while (postorder != NULL) { |
| 2426 postorder = postorder->PerformStep(zone(), &visited, &reverse_result); | 2397 postorder = postorder->PerformStep(zone(), &visited, &reverse_result); |
| 2427 } | 2398 } |
| 2428 blocks_.Rewind(0); | 2399 blocks_.Rewind(0); |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3009 // (Before each HEnterInlined, there is a non-foldable HSimulate | 2980 // (Before each HEnterInlined, there is a non-foldable HSimulate |
| 3010 // anyway, so we get the barrier in the other direction for free.) | 2981 // anyway, so we get the barrier in the other direction for free.) |
| 3011 // Simply remove all accumulated simulates without merging. This | 2982 // Simply remove all accumulated simulates without merging. This |
| 3012 // is safe because simulates after instructions with side effects | 2983 // is safe because simulates after instructions with side effects |
| 3013 // are never added to the merge list. | 2984 // are never added to the merge list. |
| 3014 while (!mergelist.is_empty()) { | 2985 while (!mergelist.is_empty()) { |
| 3015 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL); | 2986 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL); |
| 3016 } | 2987 } |
| 3017 continue; | 2988 continue; |
| 3018 } | 2989 } |
| 2990 if (current->IsReturn()) { |
| 2991 // Drop mergeable simulates in the list. This is safe because |
| 2992 // simulates after instructions with side effects are never added |
| 2993 // to the merge list. |
| 2994 while (!mergelist.is_empty()) { |
| 2995 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL); |
| 2996 } |
| 2997 continue; |
| 2998 } |
| 3019 // Skip the non-simulates and the first simulate. | 2999 // Skip the non-simulates and the first simulate. |
| 3020 if (!current->IsSimulate()) continue; | 3000 if (!current->IsSimulate()) continue; |
| 3021 if (first) { | 3001 if (first) { |
| 3022 first = false; | 3002 first = false; |
| 3023 continue; | 3003 continue; |
| 3024 } | 3004 } |
| 3025 HSimulate* current_simulate = HSimulate::cast(current); | 3005 HSimulate* current_simulate = HSimulate::cast(current); |
| 3026 if ((current_simulate->previous()->HasObservableSideEffects() && | 3006 if ((current_simulate->previous()->HasObservableSideEffects() && |
| 3027 !current_simulate->next()->IsSimulate()) || | 3007 !current_simulate->next()->IsSimulate()) || |
| 3028 !current_simulate->is_candidate_for_removal()) { | 3008 !current_simulate->is_candidate_for_removal()) { |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3545 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, | 3525 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, |
| 3546 CompilationInfo* info, | 3526 CompilationInfo* info, |
| 3547 InliningKind inlining_kind) | 3527 InliningKind inlining_kind) |
| 3548 : owner_(owner), | 3528 : owner_(owner), |
| 3549 compilation_info_(info), | 3529 compilation_info_(info), |
| 3550 call_context_(NULL), | 3530 call_context_(NULL), |
| 3551 inlining_kind_(inlining_kind), | 3531 inlining_kind_(inlining_kind), |
| 3552 function_return_(NULL), | 3532 function_return_(NULL), |
| 3553 test_context_(NULL), | 3533 test_context_(NULL), |
| 3554 entry_(NULL), | 3534 entry_(NULL), |
| 3535 arguments_object_(NULL), |
| 3555 arguments_elements_(NULL), | 3536 arguments_elements_(NULL), |
| 3556 outer_(owner->function_state()) { | 3537 outer_(owner->function_state()) { |
| 3557 if (outer_ != NULL) { | 3538 if (outer_ != NULL) { |
| 3558 // State for an inline function. | 3539 // State for an inline function. |
| 3559 if (owner->ast_context()->IsTest()) { | 3540 if (owner->ast_context()->IsTest()) { |
| 3560 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); | 3541 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); |
| 3561 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); | 3542 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); |
| 3562 if_true->MarkAsInlineReturnTarget(owner->current_block()); | 3543 if_true->MarkAsInlineReturnTarget(owner->current_block()); |
| 3563 if_false->MarkAsInlineReturnTarget(owner->current_block()); | 3544 if_false->MarkAsInlineReturnTarget(owner->current_block()); |
| 3564 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); | 3545 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3817 } while (false) | 3798 } while (false) |
| 3818 | 3799 |
| 3819 | 3800 |
| 3820 #define CHECK_ALIVE(call) \ | 3801 #define CHECK_ALIVE(call) \ |
| 3821 do { \ | 3802 do { \ |
| 3822 call; \ | 3803 call; \ |
| 3823 if (HasStackOverflow() || current_block() == NULL) return; \ | 3804 if (HasStackOverflow() || current_block() == NULL) return; \ |
| 3824 } while (false) | 3805 } while (false) |
| 3825 | 3806 |
| 3826 | 3807 |
| 3808 #define CHECK_ALIVE_OR_RETURN(call, value) \ |
| 3809 do { \ |
| 3810 call; \ |
| 3811 if (HasStackOverflow() || current_block() == NULL) return value; \ |
| 3812 } while (false) |
| 3813 |
| 3814 |
| 3827 void HOptimizedGraphBuilder::Bailout(const char* reason) { | 3815 void HOptimizedGraphBuilder::Bailout(const char* reason) { |
| 3828 current_info()->set_bailout_reason(reason); | 3816 current_info()->set_bailout_reason(reason); |
| 3829 SetStackOverflow(); | 3817 SetStackOverflow(); |
| 3830 } | 3818 } |
| 3831 | 3819 |
| 3832 | 3820 |
| 3833 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { | 3821 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { |
| 3834 EffectContext for_effect(this); | 3822 EffectContext for_effect(this); |
| 3835 Visit(expr); | 3823 Visit(expr); |
| 3836 } | 3824 } |
| (...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4692 | 4680 |
| 4693 while (!arguments.is_empty()) { | 4681 while (!arguments.is_empty()) { |
| 4694 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); | 4682 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); |
| 4695 } | 4683 } |
| 4696 return call; | 4684 return call; |
| 4697 } | 4685 } |
| 4698 | 4686 |
| 4699 | 4687 |
| 4700 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 4688 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { |
| 4701 HConstant* undefined_constant = new(zone()) HConstant( | 4689 HConstant* undefined_constant = new(zone()) HConstant( |
| 4702 isolate()->factory()->undefined_value(), Representation::Tagged()); | 4690 isolate()->factory()->undefined_value()); |
| 4703 AddInstruction(undefined_constant); | 4691 AddInstruction(undefined_constant); |
| 4704 graph()->set_undefined_constant(undefined_constant); | 4692 graph()->set_undefined_constant(undefined_constant); |
| 4705 | 4693 |
| 4706 HArgumentsObject* object = new(zone()) HArgumentsObject; | 4694 // Create an arguments object containing the initial parameters. Set the |
| 4707 AddInstruction(object); | 4695 // initial values of parameters including "this" having parameter index 0. |
| 4708 graph()->SetArgumentsObject(object); | |
| 4709 | |
| 4710 // Set the initial values of parameters including "this". "This" has | |
| 4711 // parameter index 0. | |
| 4712 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 4696 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
| 4713 | 4697 HArgumentsObject* arguments_object = |
| 4698 new(zone()) HArgumentsObject(environment()->parameter_count(), zone()); |
| 4714 for (int i = 0; i < environment()->parameter_count(); ++i) { | 4699 for (int i = 0; i < environment()->parameter_count(); ++i) { |
| 4715 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); | 4700 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); |
| 4701 arguments_object->AddArgument(parameter, zone()); |
| 4716 environment()->Bind(i, parameter); | 4702 environment()->Bind(i, parameter); |
| 4717 } | 4703 } |
| 4704 AddInstruction(arguments_object); |
| 4705 graph()->SetArgumentsObject(arguments_object); |
| 4718 | 4706 |
| 4719 // First special is HContext. | 4707 // First special is HContext. |
| 4720 HInstruction* context = AddInstruction(new(zone()) HContext); | 4708 HInstruction* context = AddInstruction(new(zone()) HContext); |
| 4721 environment()->BindContext(context); | 4709 environment()->BindContext(context); |
| 4722 | 4710 |
| 4723 // Initialize specials and locals to undefined. | 4711 // Initialize specials and locals to undefined. |
| 4724 for (int i = environment()->parameter_count() + 1; | 4712 for (int i = environment()->parameter_count() + 1; |
| 4725 i < environment()->length(); | 4713 i < environment()->length(); |
| 4726 ++i) { | 4714 ++i) { |
| 4727 environment()->Bind(i, undefined_constant); | 4715 environment()->Bind(i, undefined_constant); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5022 // Generate a compare and branch. | 5010 // Generate a compare and branch. |
| 5023 CHECK_ALIVE(VisitForValue(clause->label())); | 5011 CHECK_ALIVE(VisitForValue(clause->label())); |
| 5024 HValue* label_value = Pop(); | 5012 HValue* label_value = Pop(); |
| 5025 | 5013 |
| 5026 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 5014 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
| 5027 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 5015 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
| 5028 | 5016 |
| 5029 HControlInstruction* compare; | 5017 HControlInstruction* compare; |
| 5030 | 5018 |
| 5031 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 5019 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
| 5032 if (!clause->IsSmiCompare()) { | 5020 if (!clause->compare_type()->Is(Type::Integer31())) { |
| 5033 AddSoftDeoptimize(); | 5021 AddSoftDeoptimize(); |
| 5034 } | 5022 } |
| 5035 | 5023 |
| 5036 HCompareIDAndBranch* compare_ = | 5024 HCompareIDAndBranch* compare_ = |
| 5037 new(zone()) HCompareIDAndBranch(tag_value, | 5025 new(zone()) HCompareIDAndBranch(tag_value, |
| 5038 label_value, | 5026 label_value, |
| 5039 Token::EQ_STRICT); | 5027 Token::EQ_STRICT); |
| 5040 compare_->set_observed_input_representation( | 5028 compare_->set_observed_input_representation( |
| 5041 Representation::Integer32(), Representation::Integer32()); | 5029 Representation::Smi(), Representation::Smi()); |
| 5042 compare = compare_; | 5030 compare = compare_; |
| 5043 } else { | 5031 } else { |
| 5044 compare = new(zone()) HStringCompareAndBranch(context, tag_value, | 5032 compare = new(zone()) HStringCompareAndBranch(context, tag_value, |
| 5045 label_value, | 5033 label_value, |
| 5046 Token::EQ_STRICT); | 5034 Token::EQ_STRICT); |
| 5047 } | 5035 } |
| 5048 | 5036 |
| 5049 compare->SetSuccessorAt(0, body_block); | 5037 compare->SetSuccessorAt(0, body_block); |
| 5050 compare->SetSuccessorAt(1, next_test_block); | 5038 compare->SetSuccessorAt(1, next_test_block); |
| 5051 current_block()->Finish(compare); | 5039 current_block()->Finish(compare); |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5396 set_current_block(loop_entry); | 5384 set_current_block(loop_entry); |
| 5397 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | 5385 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); |
| 5398 | 5386 |
| 5399 HValue* index = environment()->ExpressionStackAt(0); | 5387 HValue* index = environment()->ExpressionStackAt(0); |
| 5400 HValue* limit = environment()->ExpressionStackAt(1); | 5388 HValue* limit = environment()->ExpressionStackAt(1); |
| 5401 | 5389 |
| 5402 // Check that we still have more keys. | 5390 // Check that we still have more keys. |
| 5403 HCompareIDAndBranch* compare_index = | 5391 HCompareIDAndBranch* compare_index = |
| 5404 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); | 5392 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); |
| 5405 compare_index->set_observed_input_representation( | 5393 compare_index->set_observed_input_representation( |
| 5406 Representation::Integer32(), Representation::Integer32()); | 5394 Representation::Smi(), Representation::Smi()); |
| 5407 | 5395 |
| 5408 HBasicBlock* loop_body = graph()->CreateBasicBlock(); | 5396 HBasicBlock* loop_body = graph()->CreateBasicBlock(); |
| 5409 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); | 5397 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); |
| 5410 | 5398 |
| 5411 compare_index->SetSuccessorAt(0, loop_body); | 5399 compare_index->SetSuccessorAt(0, loop_body); |
| 5412 compare_index->SetSuccessorAt(1, loop_successor); | 5400 compare_index->SetSuccessorAt(1, loop_successor); |
| 5413 current_block()->Finish(compare_index); | 5401 current_block()->Finish(compare_index); |
| 5414 | 5402 |
| 5415 set_current_block(loop_successor); | 5403 set_current_block(loop_successor); |
| 5416 Drop(5); | 5404 Drop(5); |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5618 case Variable::UNALLOCATED: { | 5606 case Variable::UNALLOCATED: { |
| 5619 if (IsLexicalVariableMode(variable->mode())) { | 5607 if (IsLexicalVariableMode(variable->mode())) { |
| 5620 // TODO(rossberg): should this be an ASSERT? | 5608 // TODO(rossberg): should this be an ASSERT? |
| 5621 return Bailout("reference to global lexical variable"); | 5609 return Bailout("reference to global lexical variable"); |
| 5622 } | 5610 } |
| 5623 // Handle known global constants like 'undefined' specially to avoid a | 5611 // Handle known global constants like 'undefined' specially to avoid a |
| 5624 // load from a global cell for them. | 5612 // load from a global cell for them. |
| 5625 Handle<Object> constant_value = | 5613 Handle<Object> constant_value = |
| 5626 isolate()->factory()->GlobalConstantFor(variable->name()); | 5614 isolate()->factory()->GlobalConstantFor(variable->name()); |
| 5627 if (!constant_value.is_null()) { | 5615 if (!constant_value.is_null()) { |
| 5628 HConstant* instr = | 5616 HConstant* instr = new(zone()) HConstant(constant_value); |
| 5629 new(zone()) HConstant(constant_value, Representation::Tagged()); | |
| 5630 return ast_context()->ReturnInstruction(instr, expr->id()); | 5617 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5631 } | 5618 } |
| 5632 | 5619 |
| 5633 LookupResult lookup(isolate()); | 5620 LookupResult lookup(isolate()); |
| 5634 GlobalPropertyAccess type = | 5621 GlobalPropertyAccess type = |
| 5635 LookupGlobalProperty(variable, &lookup, false); | 5622 LookupGlobalProperty(variable, &lookup, false); |
| 5636 | 5623 |
| 5637 if (type == kUseCell && | 5624 if (type == kUseCell && |
| 5638 current_info()->global_object()->IsAccessCheckNeeded()) { | 5625 current_info()->global_object()->IsAccessCheckNeeded()) { |
| 5639 type = kUseGeneric; | 5626 type = kUseGeneric; |
| 5640 } | 5627 } |
| 5641 | 5628 |
| 5642 if (type == kUseCell) { | 5629 if (type == kUseCell) { |
| 5643 Handle<GlobalObject> global(current_info()->global_object()); | 5630 Handle<GlobalObject> global(current_info()->global_object()); |
| 5644 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5631 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5645 HLoadGlobalCell* instr = | 5632 HLoadGlobalCell* instr = |
| 5646 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); | 5633 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); |
| 5647 return ast_context()->ReturnInstruction(instr, expr->id()); | 5634 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5648 } else { | 5635 } else { |
| 5649 HValue* context = environment()->LookupContext(); | 5636 HValue* context = environment()->LookupContext(); |
| 5650 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 5637 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 5651 AddInstruction(global_object); | 5638 AddInstruction(global_object); |
| 5652 HLoadGlobalGeneric* instr = | 5639 HLoadGlobalGeneric* instr = |
| 5653 new(zone()) HLoadGlobalGeneric(context, | 5640 new(zone()) HLoadGlobalGeneric(context, |
| 5654 global_object, | 5641 global_object, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 5679 case Variable::LOOKUP: | 5666 case Variable::LOOKUP: |
| 5680 return Bailout("reference to a variable which requires dynamic lookup"); | 5667 return Bailout("reference to a variable which requires dynamic lookup"); |
| 5681 } | 5668 } |
| 5682 } | 5669 } |
| 5683 | 5670 |
| 5684 | 5671 |
| 5685 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 5672 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { |
| 5686 ASSERT(!HasStackOverflow()); | 5673 ASSERT(!HasStackOverflow()); |
| 5687 ASSERT(current_block() != NULL); | 5674 ASSERT(current_block() != NULL); |
| 5688 ASSERT(current_block()->HasPredecessor()); | 5675 ASSERT(current_block()->HasPredecessor()); |
| 5689 HConstant* instr = | 5676 HConstant* instr = new(zone()) HConstant(expr->handle()); |
| 5690 new(zone()) HConstant(expr->handle(), Representation::None()); | |
| 5691 return ast_context()->ReturnInstruction(instr, expr->id()); | 5677 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5692 } | 5678 } |
| 5693 | 5679 |
| 5694 | 5680 |
| 5695 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 5681 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 5696 ASSERT(!HasStackOverflow()); | 5682 ASSERT(!HasStackOverflow()); |
| 5697 ASSERT(current_block() != NULL); | 5683 ASSERT(current_block() != NULL); |
| 5698 ASSERT(current_block()->HasPredecessor()); | 5684 ASSERT(current_block()->HasPredecessor()); |
| 5699 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5685 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 5700 Handle<FixedArray> literals(closure->literals()); | 5686 Handle<FixedArray> literals(closure->literals()); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5905 NoObservableSideEffectsScope no_effects(this); | 5891 NoObservableSideEffectsScope no_effects(this); |
| 5906 Handle<FixedArray> closure_literals(closure->literals(), isolate()); | 5892 Handle<FixedArray> closure_literals(closure->literals(), isolate()); |
| 5907 Handle<FixedArray> constant_properties = expr->constant_properties(); | 5893 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 5908 int literal_index = expr->literal_index(); | 5894 int literal_index = expr->literal_index(); |
| 5909 int flags = expr->fast_elements() | 5895 int flags = expr->fast_elements() |
| 5910 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; | 5896 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; |
| 5911 flags |= expr->has_function() | 5897 flags |= expr->has_function() |
| 5912 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; | 5898 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; |
| 5913 | 5899 |
| 5914 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 5900 AddInstruction(new(zone()) HPushArgument(AddInstruction( |
| 5915 new(zone()) HConstant(closure_literals, Representation::Tagged())))); | 5901 new(zone()) HConstant(closure_literals)))); |
| 5916 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 5902 AddInstruction(new(zone()) HPushArgument(AddInstruction( |
| 5917 new(zone()) HConstant(literal_index, Representation::Tagged())))); | 5903 new(zone()) HConstant(literal_index)))); |
| 5918 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 5904 AddInstruction(new(zone()) HPushArgument(AddInstruction( |
| 5919 new(zone()) HConstant(constant_properties, Representation::Tagged())))); | 5905 new(zone()) HConstant(constant_properties)))); |
| 5920 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 5906 AddInstruction(new(zone()) HPushArgument(AddInstruction( |
| 5921 new(zone()) HConstant(flags, Representation::Tagged())))); | 5907 new(zone()) HConstant(flags)))); |
| 5922 | 5908 |
| 5923 Runtime::FunctionId function_id = | 5909 Runtime::FunctionId function_id = |
| 5924 (expr->depth() > 1 || expr->may_store_doubles()) | 5910 (expr->depth() > 1 || expr->may_store_doubles()) |
| 5925 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; | 5911 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; |
| 5926 literal = AddInstruction( | 5912 literal = AddInstruction( |
| 5927 new(zone()) HCallRuntime(context, | 5913 new(zone()) HCallRuntime(context, |
| 5928 isolate()->factory()->empty_string(), | 5914 isolate()->factory()->empty_string(), |
| 5929 Runtime::FunctionForId(function_id), | 5915 Runtime::FunctionForId(function_id), |
| 5930 4)); | 5916 4)); |
| 5931 } | 5917 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6059 data_size, | 6045 data_size, |
| 6060 pointer_size, | 6046 pointer_size, |
| 6061 mode); | 6047 mode); |
| 6062 } else { | 6048 } else { |
| 6063 NoObservableSideEffectsScope no_effects(this); | 6049 NoObservableSideEffectsScope no_effects(this); |
| 6064 // Boilerplate already exists and constant elements are never accessed, | 6050 // Boilerplate already exists and constant elements are never accessed, |
| 6065 // pass an empty fixed array to the runtime function instead. | 6051 // pass an empty fixed array to the runtime function instead. |
| 6066 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 6052 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
| 6067 int literal_index = expr->literal_index(); | 6053 int literal_index = expr->literal_index(); |
| 6068 | 6054 |
| 6069 // TODO(mstarzinger): The following check and deopt is actually obsolete | |
| 6070 // but test cases for the tick processor fails because profile differs. | |
| 6071 | |
| 6072 // Deopt if the array literal boilerplate ElementsKind is of a type | |
| 6073 // different than the expected one. The check isn't necessary if the | |
| 6074 // boilerplate has already been converted to TERMINAL_FAST_ELEMENTS_KIND. | |
| 6075 if (CanTransitionToMoreGeneralFastElementsKind( | |
| 6076 boilerplate_elements_kind, true)) { | |
| 6077 IfBuilder builder(this); | |
| 6078 HValue* boilerplate = AddInstruction(new(zone()) | |
| 6079 HConstant(original_boilerplate_object, Representation::Tagged())); | |
| 6080 HValue* elements_kind = AddInstruction(new(zone()) | |
| 6081 HElementsKind(boilerplate)); | |
| 6082 HValue* expected_kind = AddInstruction(new(zone()) | |
| 6083 HConstant(boilerplate_elements_kind, Representation::Integer32())); | |
| 6084 builder.IfCompare(elements_kind, expected_kind, Token::EQ); | |
| 6085 builder.Then(); | |
| 6086 builder.ElseDeopt(); | |
| 6087 } | |
| 6088 | |
| 6089 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 6055 AddInstruction(new(zone()) HPushArgument(AddInstruction( |
| 6090 new(zone()) HConstant(literals, Representation::Tagged())))); | 6056 new(zone()) HConstant(literals)))); |
| 6091 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 6057 AddInstruction(new(zone()) HPushArgument(AddInstruction( |
| 6092 new(zone()) HConstant(literal_index, Representation::Tagged())))); | 6058 new(zone()) HConstant(literal_index)))); |
| 6093 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 6059 AddInstruction(new(zone()) HPushArgument(AddInstruction( |
| 6094 new(zone()) HConstant(constants, Representation::Tagged())))); | 6060 new(zone()) HConstant(constants)))); |
| 6095 | 6061 |
| 6096 Runtime::FunctionId function_id = (expr->depth() > 1) | 6062 Runtime::FunctionId function_id = (expr->depth() > 1) |
| 6097 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 6063 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
| 6098 literal = AddInstruction( | 6064 literal = AddInstruction( |
| 6099 new(zone()) HCallRuntime(context, | 6065 new(zone()) HCallRuntime(context, |
| 6100 isolate()->factory()->empty_string(), | 6066 isolate()->factory()->empty_string(), |
| 6101 Runtime::FunctionForId(function_id), | 6067 Runtime::FunctionForId(function_id), |
| 6102 3)); | 6068 3)); |
| 6103 } | 6069 } |
| 6104 | 6070 |
| 6105 // The array is expected in the bailout environment during computation | 6071 // The array is expected in the bailout environment during computation |
| 6106 // of the property values and is the value of the entire expression. | 6072 // of the property values and is the value of the entire expression. |
| 6107 Push(literal); | 6073 Push(literal); |
| 6074 // The literal index is on the stack, too. |
| 6075 Push(AddInstruction(new(zone()) HConstant(expr->literal_index()))); |
| 6108 | 6076 |
| 6109 HInstruction* elements = NULL; | 6077 HInstruction* elements = NULL; |
| 6110 | 6078 |
| 6111 for (int i = 0; i < length; i++) { | 6079 for (int i = 0; i < length; i++) { |
| 6112 Expression* subexpr = subexprs->at(i); | 6080 Expression* subexpr = subexprs->at(i); |
| 6113 // If the subexpression is a literal or a simple materialized literal it | 6081 // If the subexpression is a literal or a simple materialized literal it |
| 6114 // is already set in the cloned array. | 6082 // is already set in the cloned array. |
| 6115 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 6083 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 6116 | 6084 |
| 6117 CHECK_ALIVE(VisitForValue(subexpr)); | 6085 CHECK_ALIVE(VisitForValue(subexpr)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 6135 value, | 6103 value, |
| 6136 boilerplate_elements_kind)); | 6104 boilerplate_elements_kind)); |
| 6137 break; | 6105 break; |
| 6138 default: | 6106 default: |
| 6139 UNREACHABLE(); | 6107 UNREACHABLE(); |
| 6140 break; | 6108 break; |
| 6141 } | 6109 } |
| 6142 | 6110 |
| 6143 AddSimulate(expr->GetIdForElement(i)); | 6111 AddSimulate(expr->GetIdForElement(i)); |
| 6144 } | 6112 } |
| 6113 |
| 6114 Drop(1); // array literal index |
| 6145 return ast_context()->ReturnValue(Pop()); | 6115 return ast_context()->ReturnValue(Pop()); |
| 6146 } | 6116 } |
| 6147 | 6117 |
| 6148 | 6118 |
| 6149 // Sets the lookup result and returns true if the load/store can be inlined. | 6119 // Sets the lookup result and returns true if the load/store can be inlined. |
| 6150 static bool ComputeLoadStoreField(Handle<Map> type, | 6120 static bool ComputeLoadStoreField(Handle<Map> type, |
| 6151 Handle<String> name, | 6121 Handle<String> name, |
| 6152 LookupResult* lookup, | 6122 LookupResult* lookup, |
| 6153 bool is_store) { | 6123 bool is_store) { |
| 6154 if (type->has_named_interceptor()) { | 6124 if (type->has_named_interceptor()) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6238 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 6208 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
| 6239 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | 6209 Representation representation = ComputeLoadStoreRepresentation(map, lookup); |
| 6240 bool transition_to_field = lookup->IsTransitionToField(*map); | 6210 bool transition_to_field = lookup->IsTransitionToField(*map); |
| 6241 | 6211 |
| 6242 HStoreNamedField *instr; | 6212 HStoreNamedField *instr; |
| 6243 if (FLAG_track_double_fields && representation.IsDouble()) { | 6213 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 6244 if (transition_to_field) { | 6214 if (transition_to_field) { |
| 6245 // The store requires a mutable HeapNumber to be allocated. | 6215 // The store requires a mutable HeapNumber to be allocated. |
| 6246 NoObservableSideEffectsScope no_side_effects(this); | 6216 NoObservableSideEffectsScope no_side_effects(this); |
| 6247 HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant( | 6217 HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant( |
| 6248 HeapNumber::kSize, Representation::Integer32())); | 6218 HeapNumber::kSize)); |
| 6249 HInstruction* double_box = AddInstruction(new(zone()) HAllocate( | 6219 HInstruction* double_box = AddInstruction(new(zone()) HAllocate( |
| 6250 environment()->LookupContext(), heap_number_size, | 6220 environment()->LookupContext(), heap_number_size, |
| 6251 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); | 6221 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); |
| 6252 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); | 6222 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); |
| 6253 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 6223 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
| 6254 value, Representation::Double()); | 6224 value, Representation::Double()); |
| 6255 instr = new(zone()) HStoreNamedField(object, field_access, double_box); | 6225 instr = new(zone()) HStoreNamedField(object, field_access, double_box); |
| 6256 } else { | 6226 } else { |
| 6257 // Already holds a HeapNumber; load the box and write its value field. | 6227 // Already holds a HeapNumber; load the box and write its value field. |
| 6258 HInstruction* double_box = AddLoad(object, field_access); | 6228 HInstruction* double_box = AddLoad(object, field_access); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6314 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 6284 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 6315 AddCheckMapsWithTransitions(object, map); | 6285 AddCheckMapsWithTransitions(object, map); |
| 6316 return BuildStoreNamedField(object, name, value, map, &lookup); | 6286 return BuildStoreNamedField(object, name, value, map, &lookup); |
| 6317 } | 6287 } |
| 6318 | 6288 |
| 6319 // No luck, do a generic store. | 6289 // No luck, do a generic store. |
| 6320 return BuildStoreNamedGeneric(object, name, value); | 6290 return BuildStoreNamedGeneric(object, name, value); |
| 6321 } | 6291 } |
| 6322 | 6292 |
| 6323 | 6293 |
| 6324 bool HOptimizedGraphBuilder::HandlePolymorphicArrayLengthLoad( | 6294 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( |
| 6325 Property* expr, | 6295 Property* expr, |
| 6326 HValue* object, | 6296 HValue* object, |
| 6327 SmallMapList* types, | 6297 SmallMapList* types, |
| 6328 Handle<String> name) { | 6298 Handle<String> name) { |
| 6329 if (!name->Equals(isolate()->heap()->length_string())) return false; | |
| 6330 | |
| 6331 for (int i = 0; i < types->length(); i++) { | |
| 6332 if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false; | |
| 6333 } | |
| 6334 | |
| 6335 BuildCheckNonSmi(object); | |
| 6336 | |
| 6337 HInstruction* typecheck = | |
| 6338 AddInstruction(HCheckMaps::New(object, types, zone())); | |
| 6339 HInstruction* instr = new(zone()) | |
| 6340 HLoadNamedField(object, HObjectAccess::ForArrayLength(), typecheck); | |
| 6341 | |
| 6342 instr->set_position(expr->position()); | |
| 6343 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 6344 return true; | |
| 6345 } | |
| 6346 | |
| 6347 | |
| 6348 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | |
| 6349 HValue* object, | |
| 6350 SmallMapList* types, | |
| 6351 Handle<String> name) { | |
| 6352 | |
| 6353 if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) | |
| 6354 return; | |
| 6355 | |
| 6356 BuildCheckNonSmi(object); | |
| 6357 | |
| 6358 // Use monomorphic load if property lookup results in the same field index | 6299 // Use monomorphic load if property lookup results in the same field index |
| 6359 // for all maps. Requires special map check on the set of all handled maps. | 6300 // for all maps. Requires special map check on the set of all handled maps. |
| 6360 HInstruction* instr = NULL; | 6301 if (types->length() > kMaxLoadPolymorphism) return NULL; |
| 6302 |
| 6361 LookupResult lookup(isolate()); | 6303 LookupResult lookup(isolate()); |
| 6362 int count; | 6304 int count; |
| 6363 Representation representation = Representation::None(); | 6305 Representation representation = Representation::None(); |
| 6364 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 6306 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 6365 for (count = 0; | 6307 for (count = 0; count < types->length(); ++count) { |
| 6366 count < types->length() && count < kMaxLoadPolymorphism; | |
| 6367 ++count) { | |
| 6368 Handle<Map> map = types->at(count); | 6308 Handle<Map> map = types->at(count); |
| 6369 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 6309 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| 6370 | 6310 |
| 6371 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 6311 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 6312 Representation new_representation = |
| 6313 ComputeLoadStoreRepresentation(map, &lookup); |
| 6314 |
| 6315 if (count == 0) { |
| 6316 // First time through the loop; set access and representation. |
| 6317 access = new_access; |
| 6318 } else if (!representation.IsCompatibleForLoad(new_representation)) { |
| 6319 // Representations did not match. |
| 6320 break; |
| 6321 } else if (access.offset() != new_access.offset()) { |
| 6322 // Offsets did not match. |
| 6323 break; |
| 6324 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 6325 // In-objectness did not match. |
| 6326 break; |
| 6327 } |
| 6328 representation = representation.generalize(new_representation); |
| 6329 } |
| 6330 |
| 6331 if (count != types->length()) return NULL; |
| 6332 |
| 6333 // Everything matched; can use monomorphic load. |
| 6334 BuildCheckNonSmi(object); |
| 6335 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 6336 return BuildLoadNamedField(object, access, representation); |
| 6337 } |
| 6338 |
| 6339 |
| 6340 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| 6341 Property* expr, |
| 6342 HValue* object, |
| 6343 SmallMapList* types, |
| 6344 Handle<String> name) { |
| 6345 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( |
| 6346 expr, object, types, name); |
| 6347 if (instr == NULL) { |
| 6348 // Something did not match; must use a polymorphic load. |
| 6349 BuildCheckNonSmi(object); |
| 6350 HValue* context = environment()->LookupContext(); |
| 6351 instr = new(zone()) HLoadNamedFieldPolymorphic( |
| 6352 context, object, types, name, zone()); |
| 6353 } |
| 6354 |
| 6355 instr->set_position(expr->position()); |
| 6356 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6357 } |
| 6358 |
| 6359 |
| 6360 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
| 6361 Assignment* expr, |
| 6362 HValue* object, |
| 6363 HValue* value, |
| 6364 SmallMapList* types, |
| 6365 Handle<String> name) { |
| 6366 // Use monomorphic store if property lookup results in the same field index |
| 6367 // for all maps. Requires special map check on the set of all handled maps. |
| 6368 if (types->length() > kMaxStorePolymorphism) return false; |
| 6369 |
| 6370 // TODO(verwaest): Merge the checking logic with the code in |
| 6371 // TryLoadPolymorphicAsMonomorphic. |
| 6372 LookupResult lookup(isolate()); |
| 6373 int count; |
| 6374 Representation representation = Representation::None(); |
| 6375 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 6376 for (count = 0; count < types->length(); ++count) { |
| 6377 Handle<Map> map = types->at(count); |
| 6378 // Pass false to ignore transitions. |
| 6379 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| 6380 |
| 6381 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 6372 Representation new_representation = | 6382 Representation new_representation = |
| 6373 ComputeLoadStoreRepresentation(map, &lookup); | 6383 ComputeLoadStoreRepresentation(map, &lookup); |
| 6374 | 6384 |
| 6375 if (count == 0) { | 6385 if (count == 0) { |
| 6376 // First time through the loop; set access and representation. | 6386 // First time through the loop; set access and representation. |
| 6377 access = new_access; | 6387 access = new_access; |
| 6378 representation = new_representation; | 6388 representation = new_representation; |
| 6379 } else if (!representation.IsCompatibleForLoad(new_representation)) { | 6389 } else if (!representation.IsCompatibleForStore(new_representation)) { |
| 6380 // Representations did not match. | 6390 // Representations did not match. |
| 6381 break; | 6391 break; |
| 6382 } else if (access.offset() != new_access.offset()) { | 6392 } else if (access.offset() != new_access.offset()) { |
| 6383 // Offsets did not match. | 6393 // Offsets did not match. |
| 6384 break; | 6394 break; |
| 6385 } else if (access.IsInobject() != new_access.IsInobject()) { | 6395 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 6386 // In-objectness did not match. | 6396 // In-objectness did not match. |
| 6387 break; | 6397 break; |
| 6388 } | 6398 } |
| 6389 } | 6399 } |
| 6390 | 6400 |
| 6391 if (count == types->length()) { | 6401 if (count != types->length()) return false; |
| 6392 // Everything matched; can use monomorphic load. | |
| 6393 AddInstruction(HCheckMaps::New(object, types, zone())); | |
| 6394 instr = BuildLoadNamedField(object, access, representation); | |
| 6395 } else { | |
| 6396 // Something did not match; must use a polymorphic load. | |
| 6397 HValue* context = environment()->LookupContext(); | |
| 6398 instr = new(zone()) HLoadNamedFieldPolymorphic( | |
| 6399 context, object, types, name, zone()); | |
| 6400 } | |
| 6401 | 6402 |
| 6402 instr->set_position(expr->position()); | 6403 // Everything matched; can use monomorphic store. |
| 6403 return ast_context()->ReturnInstruction(instr, expr->id()); | 6404 BuildCheckNonSmi(object); |
| 6405 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 6406 HInstruction* store; |
| 6407 CHECK_ALIVE_OR_RETURN( |
| 6408 store = BuildStoreNamedField(object, name, value, types->at(0), &lookup), |
| 6409 true); |
| 6410 Push(value); |
| 6411 store->set_position(expr->position()); |
| 6412 AddInstruction(store); |
| 6413 AddSimulate(expr->AssignmentId()); |
| 6414 ast_context()->ReturnValue(Pop()); |
| 6415 return true; |
| 6404 } | 6416 } |
| 6405 | 6417 |
| 6406 | 6418 |
| 6407 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 6419 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 6408 Assignment* expr, | 6420 Assignment* expr, |
| 6409 HValue* object, | 6421 HValue* object, |
| 6410 HValue* value, | 6422 HValue* value, |
| 6411 SmallMapList* types, | 6423 SmallMapList* types, |
| 6412 Handle<String> name) { | 6424 Handle<String> name) { |
| 6425 if (TryStorePolymorphicAsMonomorphic(expr, object, value, types, name)) { |
| 6426 return; |
| 6427 } |
| 6428 |
| 6413 // TODO(ager): We should recognize when the prototype chains for different | 6429 // TODO(ager): We should recognize when the prototype chains for different |
| 6414 // maps are identical. In that case we can avoid repeatedly generating the | 6430 // maps are identical. In that case we can avoid repeatedly generating the |
| 6415 // same prototype map checks. | 6431 // same prototype map checks. |
| 6416 int count = 0; | 6432 int count = 0; |
| 6417 HBasicBlock* join = NULL; | 6433 HBasicBlock* join = NULL; |
| 6418 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 6434 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 6419 Handle<Map> map = types->at(i); | 6435 Handle<Map> map = types->at(i); |
| 6420 LookupResult lookup(isolate()); | 6436 LookupResult lookup(isolate()); |
| 6421 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 6437 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 6422 if (count == 0) { | 6438 if (count == 0) { |
| 6423 BuildCheckNonSmi(object); | 6439 BuildCheckNonSmi(object); |
| 6424 join = graph()->CreateBasicBlock(); | 6440 join = graph()->CreateBasicBlock(); |
| 6425 } | 6441 } |
| 6426 ++count; | 6442 ++count; |
| 6427 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6443 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 6428 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6444 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 6429 HCompareMap* compare = | 6445 HCompareMap* compare = |
| 6430 new(zone()) HCompareMap(object, map, if_true, if_false); | 6446 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 6431 current_block()->Finish(compare); | 6447 current_block()->Finish(compare); |
| 6432 | 6448 |
| 6433 set_current_block(if_true); | 6449 set_current_block(if_true); |
| 6434 HInstruction* instr; | 6450 HInstruction* instr; |
| 6435 CHECK_ALIVE(instr = | 6451 CHECK_ALIVE( |
| 6436 BuildStoreNamedField(object, name, value, map, &lookup)); | 6452 instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
| 6437 instr->set_position(expr->position()); | 6453 instr->set_position(expr->position()); |
| 6438 // Goto will add the HSimulate for the store. | 6454 // Goto will add the HSimulate for the store. |
| 6439 AddInstruction(instr); | 6455 AddInstruction(instr); |
| 6440 if (!ast_context()->IsEffect()) Push(value); | 6456 if (!ast_context()->IsEffect()) Push(value); |
| 6441 current_block()->Goto(join); | 6457 current_block()->Goto(join); |
| 6442 | 6458 |
| 6443 set_current_block(if_false); | 6459 set_current_block(if_false); |
| 6444 } | 6460 } |
| 6445 } | 6461 } |
| 6446 | 6462 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 6470 Drop(1); | 6486 Drop(1); |
| 6471 } | 6487 } |
| 6472 } | 6488 } |
| 6473 return ast_context()->ReturnValue(value); | 6489 return ast_context()->ReturnValue(value); |
| 6474 } | 6490 } |
| 6475 } | 6491 } |
| 6476 | 6492 |
| 6477 ASSERT(join != NULL); | 6493 ASSERT(join != NULL); |
| 6478 join->SetJoinId(expr->id()); | 6494 join->SetJoinId(expr->id()); |
| 6479 set_current_block(join); | 6495 set_current_block(join); |
| 6480 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 6496 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 6481 } | 6497 } |
| 6482 | 6498 |
| 6483 | 6499 |
| 6484 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 6500 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 6485 Property* prop = expr->target()->AsProperty(); | 6501 Property* prop = expr->target()->AsProperty(); |
| 6486 ASSERT(prop != NULL); | 6502 ASSERT(prop != NULL); |
| 6487 CHECK_ALIVE(VisitForValue(prop->obj())); | 6503 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 6488 | 6504 |
| 6489 if (prop->key()->IsPropertyName()) { | 6505 if (prop->key()->IsPropertyName()) { |
| 6490 // Named store. | 6506 // Named store. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6565 // owning expression instead of position and ast_id separately. | 6581 // owning expression instead of position and ast_id separately. |
| 6566 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6582 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 6567 Variable* var, | 6583 Variable* var, |
| 6568 HValue* value, | 6584 HValue* value, |
| 6569 int position, | 6585 int position, |
| 6570 BailoutId ast_id) { | 6586 BailoutId ast_id) { |
| 6571 LookupResult lookup(isolate()); | 6587 LookupResult lookup(isolate()); |
| 6572 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 6588 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 6573 if (type == kUseCell) { | 6589 if (type == kUseCell) { |
| 6574 Handle<GlobalObject> global(current_info()->global_object()); | 6590 Handle<GlobalObject> global(current_info()->global_object()); |
| 6575 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 6591 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 6576 HInstruction* instr = | 6592 HInstruction* instr = |
| 6577 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 6593 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
| 6578 instr->set_position(position); | 6594 instr->set_position(position); |
| 6579 AddInstruction(instr); | 6595 AddInstruction(instr); |
| 6580 if (instr->HasObservableSideEffects()) { | 6596 if (instr->HasObservableSideEffects()) { |
| 6581 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 6597 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 6582 } | 6598 } |
| 6583 } else { | 6599 } else { |
| 6584 HValue* context = environment()->LookupContext(); | 6600 HValue* context = environment()->LookupContext(); |
| 6585 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 6601 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6681 return ast_context()->ReturnValue(Pop()); | 6697 return ast_context()->ReturnValue(Pop()); |
| 6682 | 6698 |
| 6683 } else if (prop != NULL) { | 6699 } else if (prop != NULL) { |
| 6684 if (prop->key()->IsPropertyName()) { | 6700 if (prop->key()->IsPropertyName()) { |
| 6685 // Named property. | 6701 // Named property. |
| 6686 CHECK_ALIVE(VisitForValue(prop->obj())); | 6702 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 6687 HValue* object = Top(); | 6703 HValue* object = Top(); |
| 6688 | 6704 |
| 6689 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 6705 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 6690 Handle<Map> map; | 6706 Handle<Map> map; |
| 6691 HInstruction* load; | 6707 HInstruction* load = NULL; |
| 6708 SmallMapList* types = prop->GetReceiverTypes(); |
| 6692 bool monomorphic = prop->IsMonomorphic(); | 6709 bool monomorphic = prop->IsMonomorphic(); |
| 6693 if (monomorphic) { | 6710 if (monomorphic) { |
| 6694 map = prop->GetReceiverTypes()->first(); | 6711 map = types->first(); |
| 6695 // We can't generate code for a monomorphic dict mode load so | 6712 // We can't generate code for a monomorphic dict mode load so |
| 6696 // just pretend it is not monomorphic. | 6713 // just pretend it is not monomorphic. |
| 6697 if (map->is_dictionary_map()) monomorphic = false; | 6714 if (map->is_dictionary_map()) monomorphic = false; |
| 6698 } | 6715 } |
| 6699 if (monomorphic) { | 6716 if (monomorphic) { |
| 6700 Handle<JSFunction> getter; | 6717 Handle<JSFunction> getter; |
| 6701 Handle<JSObject> holder; | 6718 Handle<JSObject> holder; |
| 6702 if (LookupGetter(map, name, &getter, &holder)) { | 6719 if (LookupGetter(map, name, &getter, &holder)) { |
| 6703 load = BuildCallGetter(object, map, getter, holder); | 6720 load = BuildCallGetter(object, map, getter, holder); |
| 6704 } else { | 6721 } else { |
| 6705 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 6722 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
| 6706 } | 6723 } |
| 6707 } else { | 6724 } else if (types != NULL && types->length() > 1) { |
| 6708 load = BuildLoadNamedGeneric(object, name, prop); | 6725 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
| 6709 } | 6726 } |
| 6727 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
| 6710 PushAndAdd(load); | 6728 PushAndAdd(load); |
| 6711 if (load->HasObservableSideEffects()) { | 6729 if (load->HasObservableSideEffects()) { |
| 6712 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 6730 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 6713 } | 6731 } |
| 6714 | 6732 |
| 6715 CHECK_ALIVE(VisitForValue(expr->value())); | 6733 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6716 HValue* right = Pop(); | 6734 HValue* right = Pop(); |
| 6717 HValue* left = Pop(); | 6735 HValue* left = Pop(); |
| 6718 | 6736 |
| 6719 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 6737 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6965 return field; | 6983 return field; |
| 6966 } | 6984 } |
| 6967 | 6985 |
| 6968 | 6986 |
| 6969 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6987 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 6970 HValue* object, | 6988 HValue* object, |
| 6971 Handle<String> name, | 6989 Handle<String> name, |
| 6972 Property* expr) { | 6990 Property* expr) { |
| 6973 if (expr->IsUninitialized()) { | 6991 if (expr->IsUninitialized()) { |
| 6974 AddSoftDeoptimize(); | 6992 AddSoftDeoptimize(); |
| 6993 } else { |
| 6994 // OS::DebugBreak(); |
| 6975 } | 6995 } |
| 6976 HValue* context = environment()->LookupContext(); | 6996 HValue* context = environment()->LookupContext(); |
| 6977 return new(zone()) HLoadNamedGeneric(context, object, name); | 6997 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 6978 } | 6998 } |
| 6979 | 6999 |
| 6980 | 7000 |
| 6981 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 7001 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
| 6982 HValue* object, | 7002 HValue* object, |
| 6983 Handle<Map> map, | 7003 Handle<Map> map, |
| 6984 Handle<JSFunction> getter, | 7004 Handle<JSFunction> getter, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 7012 AddCheckMap(object, map); | 7032 AddCheckMap(object, map); |
| 7013 return BuildLoadNamedField(object, | 7033 return BuildLoadNamedField(object, |
| 7014 HObjectAccess::ForField(map, &lookup, name), | 7034 HObjectAccess::ForField(map, &lookup, name), |
| 7015 ComputeLoadStoreRepresentation(map, &lookup)); | 7035 ComputeLoadStoreRepresentation(map, &lookup)); |
| 7016 } | 7036 } |
| 7017 | 7037 |
| 7018 // Handle a load of a constant known function. | 7038 // Handle a load of a constant known function. |
| 7019 if (lookup.IsConstantFunction()) { | 7039 if (lookup.IsConstantFunction()) { |
| 7020 AddCheckMap(object, map); | 7040 AddCheckMap(object, map); |
| 7021 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 7041 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| 7022 return new(zone()) HConstant(function, Representation::Tagged()); | 7042 return new(zone()) HConstant(function); |
| 7023 } | 7043 } |
| 7024 | 7044 |
| 7025 // Handle a load from a known field somewhere in the prototype chain. | 7045 // Handle a load from a known field somewhere in the prototype chain. |
| 7026 LookupInPrototypes(map, name, &lookup); | 7046 LookupInPrototypes(map, name, &lookup); |
| 7027 if (lookup.IsField()) { | 7047 if (lookup.IsField()) { |
| 7028 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7048 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7029 Handle<JSObject> holder(lookup.holder()); | 7049 Handle<JSObject> holder(lookup.holder()); |
| 7030 Handle<Map> holder_map(holder->map()); | 7050 Handle<Map> holder_map(holder->map()); |
| 7031 AddCheckMap(object, map); | 7051 AddCheckMap(object, map); |
| 7032 AddInstruction(new(zone()) HCheckPrototypeMaps( | 7052 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7033 prototype, holder, zone(), top_info())); | 7053 prototype, holder, zone(), top_info())); |
| 7034 HValue* holder_value = AddInstruction(new(zone()) | 7054 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); |
| 7035 HConstant(holder, Representation::Tagged())); | |
| 7036 return BuildLoadNamedField(holder_value, | 7055 return BuildLoadNamedField(holder_value, |
| 7037 HObjectAccess::ForField(holder_map, &lookup, name), | 7056 HObjectAccess::ForField(holder_map, &lookup, name), |
| 7038 ComputeLoadStoreRepresentation(map, &lookup)); | 7057 ComputeLoadStoreRepresentation(map, &lookup)); |
| 7039 } | 7058 } |
| 7040 | 7059 |
| 7041 // Handle a load of a constant function somewhere in the prototype chain. | 7060 // Handle a load of a constant function somewhere in the prototype chain. |
| 7042 if (lookup.IsConstantFunction()) { | 7061 if (lookup.IsConstantFunction()) { |
| 7043 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7062 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7044 Handle<JSObject> holder(lookup.holder()); | 7063 Handle<JSObject> holder(lookup.holder()); |
| 7045 Handle<Map> holder_map(holder->map()); | 7064 Handle<Map> holder_map(holder->map()); |
| 7046 AddCheckMap(object, map); | 7065 AddCheckMap(object, map); |
| 7047 AddInstruction(new(zone()) HCheckPrototypeMaps( | 7066 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7048 prototype, holder, zone(), top_info())); | 7067 prototype, holder, zone(), top_info())); |
| 7049 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 7068 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| 7050 return new(zone()) HConstant(function, Representation::Tagged()); | 7069 return new(zone()) HConstant(function); |
| 7051 } | 7070 } |
| 7052 | 7071 |
| 7053 // No luck, do a generic load. | 7072 // No luck, do a generic load. |
| 7054 return BuildLoadNamedGeneric(object, name, expr); | 7073 return BuildLoadNamedGeneric(object, name, expr); |
| 7055 } | 7074 } |
| 7056 | 7075 |
| 7057 | 7076 |
| 7058 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 7077 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 7059 HValue* key) { | 7078 HValue* key) { |
| 7060 HValue* context = environment()->LookupContext(); | 7079 HValue* context = environment()->LookupContext(); |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7427 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 7446 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { |
| 7428 // Outermost function already has arguments on the stack. | 7447 // Outermost function already has arguments on the stack. |
| 7429 if (function_state()->outer() == NULL) return; | 7448 if (function_state()->outer() == NULL) return; |
| 7430 | 7449 |
| 7431 if (function_state()->arguments_pushed()) return; | 7450 if (function_state()->arguments_pushed()) return; |
| 7432 | 7451 |
| 7433 // Push arguments when entering inlined function. | 7452 // Push arguments when entering inlined function. |
| 7434 HEnterInlined* entry = function_state()->entry(); | 7453 HEnterInlined* entry = function_state()->entry(); |
| 7435 entry->set_arguments_pushed(); | 7454 entry->set_arguments_pushed(); |
| 7436 | 7455 |
| 7437 ZoneList<HValue*>* arguments_values = entry->arguments_values(); | 7456 HArgumentsObject* arguments = entry->arguments_object(); |
| 7457 const ZoneList<HValue*>* arguments_values = arguments->arguments_values(); |
| 7438 | 7458 |
| 7439 HInstruction* insert_after = entry; | 7459 HInstruction* insert_after = entry; |
| 7440 for (int i = 0; i < arguments_values->length(); i++) { | 7460 for (int i = 0; i < arguments_values->length(); i++) { |
| 7441 HValue* argument = arguments_values->at(i); | 7461 HValue* argument = arguments_values->at(i); |
| 7442 HInstruction* push_argument = new(zone()) HPushArgument(argument); | 7462 HInstruction* push_argument = new(zone()) HPushArgument(argument); |
| 7443 push_argument->InsertAfter(insert_after); | 7463 push_argument->InsertAfter(insert_after); |
| 7444 insert_after = push_argument; | 7464 insert_after = push_argument; |
| 7445 } | 7465 } |
| 7446 | 7466 |
| 7447 HArgumentsElements* arguments_elements = | 7467 HArgumentsElements* arguments_elements = |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7995 &target_info, | 8015 &target_info, |
| 7996 target_shared); | 8016 target_shared); |
| 7997 } | 8017 } |
| 7998 | 8018 |
| 7999 // ---------------------------------------------------------------- | 8019 // ---------------------------------------------------------------- |
| 8000 // After this point, we've made a decision to inline this function (so | 8020 // After this point, we've made a decision to inline this function (so |
| 8001 // TryInline should always return true). | 8021 // TryInline should always return true). |
| 8002 | 8022 |
| 8003 // Type-check the inlined function. | 8023 // Type-check the inlined function. |
| 8004 ASSERT(target_shared->has_deoptimization_support()); | 8024 ASSERT(target_shared->has_deoptimization_support()); |
| 8005 AstTyper::Type(&target_info); | 8025 AstTyper::Run(&target_info); |
| 8006 | 8026 |
| 8007 // Save the pending call context. Set up new one for the inlined function. | 8027 // Save the pending call context. Set up new one for the inlined function. |
| 8008 // The function state is new-allocated because we need to delete it | 8028 // The function state is new-allocated because we need to delete it |
| 8009 // in two different places. | 8029 // in two different places. |
| 8010 FunctionState* target_state = new FunctionState( | 8030 FunctionState* target_state = new FunctionState( |
| 8011 this, &target_info, inlining_kind); | 8031 this, &target_info, inlining_kind); |
| 8012 | 8032 |
| 8013 HConstant* undefined = graph()->GetConstantUndefined(); | 8033 HConstant* undefined = graph()->GetConstantUndefined(); |
| 8014 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( | 8034 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( |
| 8015 target, function, call_kind, inlining_kind); | 8035 target, function, call_kind, inlining_kind); |
| 8016 HEnvironment* inner_env = | 8036 HEnvironment* inner_env = |
| 8017 environment()->CopyForInlining(target, | 8037 environment()->CopyForInlining(target, |
| 8018 arguments_count, | 8038 arguments_count, |
| 8019 function, | 8039 function, |
| 8020 undefined, | 8040 undefined, |
| 8021 function_state()->inlining_kind(), | 8041 function_state()->inlining_kind(), |
| 8022 undefined_receiver); | 8042 undefined_receiver); |
| 8023 #ifdef V8_TARGET_ARCH_IA32 | 8043 #ifdef V8_TARGET_ARCH_IA32 |
| 8024 // IA32 only, overwrite the caller's context in the deoptimization | 8044 // IA32 only, overwrite the caller's context in the deoptimization |
| 8025 // environment with the correct one. | 8045 // environment with the correct one. |
| 8026 // | 8046 // |
| 8027 // TODO(kmillikin): implement the same inlining on other platforms so we | 8047 // TODO(kmillikin): implement the same inlining on other platforms so we |
| 8028 // can remove the unsightly ifdefs in this function. | 8048 // can remove the unsightly ifdefs in this function. |
| 8029 HConstant* context = | 8049 HConstant* context = |
| 8030 new(zone()) HConstant(Handle<Context>(target->context()), | 8050 new(zone()) HConstant(Handle<Context>(target->context())); |
| 8031 Representation::Tagged()); | |
| 8032 AddInstruction(context); | 8051 AddInstruction(context); |
| 8033 inner_env->BindContext(context); | 8052 inner_env->BindContext(context); |
| 8034 #endif | 8053 #endif |
| 8035 | 8054 |
| 8036 AddSimulate(return_id); | 8055 AddSimulate(return_id); |
| 8037 current_block()->UpdateEnvironment(inner_env); | 8056 current_block()->UpdateEnvironment(inner_env); |
| 8038 ZoneList<HValue*>* arguments_values = NULL; | 8057 HArgumentsObject* arguments_object = NULL; |
| 8039 | 8058 |
| 8040 // If the function uses arguments copy current arguments values | 8059 // If the function uses arguments object create and bind one, also copy |
| 8041 // to use them for materialization. | 8060 // current arguments values to use them for materialization. |
| 8042 if (function->scope()->arguments() != NULL) { | 8061 if (function->scope()->arguments() != NULL) { |
| 8062 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
| 8043 HEnvironment* arguments_env = inner_env->arguments_environment(); | 8063 HEnvironment* arguments_env = inner_env->arguments_environment(); |
| 8044 int arguments_count = arguments_env->parameter_count(); | 8064 int arguments_count = arguments_env->parameter_count(); |
| 8045 arguments_values = new(zone()) ZoneList<HValue*>(arguments_count, zone()); | 8065 arguments_object = new(zone()) HArgumentsObject(arguments_count, zone()); |
| 8066 inner_env->Bind(function->scope()->arguments(), arguments_object); |
| 8046 for (int i = 0; i < arguments_count; i++) { | 8067 for (int i = 0; i < arguments_count; i++) { |
| 8047 arguments_values->Add(arguments_env->Lookup(i), zone()); | 8068 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); |
| 8048 } | 8069 } |
| 8070 AddInstruction(arguments_object); |
| 8049 } | 8071 } |
| 8050 | 8072 |
| 8051 HEnterInlined* enter_inlined = | 8073 HEnterInlined* enter_inlined = |
| 8052 new(zone()) HEnterInlined(target, | 8074 new(zone()) HEnterInlined(target, |
| 8053 arguments_count, | 8075 arguments_count, |
| 8054 function, | 8076 function, |
| 8055 function_state()->inlining_kind(), | 8077 function_state()->inlining_kind(), |
| 8056 function->scope()->arguments(), | 8078 function->scope()->arguments(), |
| 8057 arguments_values, | 8079 arguments_object, |
| 8058 undefined_receiver, | 8080 undefined_receiver, |
| 8059 zone()); | 8081 zone()); |
| 8060 function_state()->set_entry(enter_inlined); | 8082 function_state()->set_entry(enter_inlined); |
| 8061 AddInstruction(enter_inlined); | 8083 AddInstruction(enter_inlined); |
| 8062 | 8084 |
| 8063 // If the function uses arguments object create and bind one. | |
| 8064 if (function->scope()->arguments() != NULL) { | |
| 8065 ASSERT(function->scope()->arguments()->IsStackAllocated()); | |
| 8066 inner_env->Bind(function->scope()->arguments(), | |
| 8067 graph()->GetArgumentsObject()); | |
| 8068 } | |
| 8069 | |
| 8070 | |
| 8071 VisitDeclarations(target_info.scope()->declarations()); | 8085 VisitDeclarations(target_info.scope()->declarations()); |
| 8072 VisitStatements(function->body()); | 8086 VisitStatements(function->body()); |
| 8073 if (HasStackOverflow()) { | 8087 if (HasStackOverflow()) { |
| 8074 // Bail out if the inline function did, as we cannot residualize a call | 8088 // Bail out if the inline function did, as we cannot residualize a call |
| 8075 // instead. | 8089 // instead. |
| 8076 TraceInline(target, caller, "inline graph construction failed"); | 8090 TraceInline(target, caller, "inline graph construction failed"); |
| 8077 target_shared->DisableOptimization("inlining bailed out"); | 8091 target_shared->DisableOptimization("inlining bailed out"); |
| 8078 inline_bailout_ = true; | 8092 inline_bailout_ = true; |
| 8079 delete target_state; | 8093 delete target_state; |
| 8080 return true; | 8094 return true; |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8366 Pop(); // Pop receiver. | 8380 Pop(); // Pop receiver. |
| 8367 HValue* context = environment()->LookupContext(); | 8381 HValue* context = environment()->LookupContext(); |
| 8368 HInstruction* result = NULL; | 8382 HInstruction* result = NULL; |
| 8369 // Use sqrt() if exponent is 0.5 or -0.5. | 8383 // Use sqrt() if exponent is 0.5 or -0.5. |
| 8370 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | 8384 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { |
| 8371 double exponent = HConstant::cast(right)->DoubleValue(); | 8385 double exponent = HConstant::cast(right)->DoubleValue(); |
| 8372 if (exponent == 0.5) { | 8386 if (exponent == 0.5) { |
| 8373 result = | 8387 result = |
| 8374 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); | 8388 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); |
| 8375 } else if (exponent == -0.5) { | 8389 } else if (exponent == -0.5) { |
| 8376 HConstant* double_one = new(zone()) HConstant( | 8390 HValue* one = graph()->GetConstant1(); |
| 8377 1, Representation::Double()); | |
| 8378 AddInstruction(double_one); | |
| 8379 HInstruction* sqrt = | 8391 HInstruction* sqrt = |
| 8380 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); | 8392 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); |
| 8381 AddInstruction(sqrt); | 8393 AddInstruction(sqrt); |
| 8382 // MathPowHalf doesn't have side effects so there's no need for | 8394 // MathPowHalf doesn't have side effects so there's no need for |
| 8383 // an environment simulation here. | 8395 // an environment simulation here. |
| 8384 ASSERT(!sqrt->HasObservableSideEffects()); | 8396 ASSERT(!sqrt->HasObservableSideEffects()); |
| 8385 result = HDiv::New(zone(), context, double_one, sqrt); | 8397 result = HDiv::New(zone(), context, one, sqrt); |
| 8386 } else if (exponent == 2.0) { | 8398 } else if (exponent == 2.0) { |
| 8387 result = HMul::New(zone(), context, left, left); | 8399 result = HMul::New(zone(), context, left, left); |
| 8388 } | 8400 } |
| 8389 } else if (right->EqualsInteger32Constant(2)) { | 8401 } else if (right->EqualsInteger32Constant(2)) { |
| 8390 result = HMul::New(zone(), context, left, left); | 8402 result = HMul::New(zone(), context, left, left); |
| 8391 } | 8403 } |
| 8392 | 8404 |
| 8393 if (result == NULL) { | 8405 if (result == NULL) { |
| 8394 result = HPower::New(zone(), left, right); | 8406 result = HPower::New(zone(), left, right); |
| 8395 } | 8407 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8492 new(zone()) HApplyArguments(function, | 8504 new(zone()) HApplyArguments(function, |
| 8493 wrapped_receiver, | 8505 wrapped_receiver, |
| 8494 length, | 8506 length, |
| 8495 elements); | 8507 elements); |
| 8496 result->set_position(expr->position()); | 8508 result->set_position(expr->position()); |
| 8497 ast_context()->ReturnInstruction(result, expr->id()); | 8509 ast_context()->ReturnInstruction(result, expr->id()); |
| 8498 return true; | 8510 return true; |
| 8499 } else { | 8511 } else { |
| 8500 // We are inside inlined function and we know exactly what is inside | 8512 // We are inside inlined function and we know exactly what is inside |
| 8501 // arguments object. But we need to be able to materialize at deopt. | 8513 // arguments object. But we need to be able to materialize at deopt. |
| 8502 // TODO(mstarzinger): For now we just ensure arguments are pushed | |
| 8503 // right after HEnterInlined, but we could be smarter about this. | |
| 8504 EnsureArgumentsArePushedForAccess(); | |
| 8505 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), | 8514 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), |
| 8506 function_state()->entry()->arguments_values()->length()); | 8515 function_state()->entry()->arguments_object()->arguments_count()); |
| 8507 HEnterInlined* entry = function_state()->entry(); | 8516 HArgumentsObject* args = function_state()->entry()->arguments_object(); |
| 8508 ZoneList<HValue*>* arguments_values = entry->arguments_values(); | 8517 const ZoneList<HValue*>* arguments_values = args->arguments_values(); |
| 8509 int arguments_count = arguments_values->length(); | 8518 int arguments_count = arguments_values->length(); |
| 8510 PushAndAdd(new(zone()) HWrapReceiver(receiver, function)); | 8519 PushAndAdd(new(zone()) HWrapReceiver(receiver, function)); |
| 8511 for (int i = 1; i < arguments_count; i++) { | 8520 for (int i = 1; i < arguments_count; i++) { |
| 8512 Push(arguments_values->at(i)); | 8521 Push(arguments_values->at(i)); |
| 8513 } | 8522 } |
| 8514 | 8523 |
| 8515 Handle<JSFunction> known_function; | 8524 Handle<JSFunction> known_function; |
| 8516 if (function->IsConstant()) { | 8525 if (function->IsConstant()) { |
| 8517 HConstant* constant_function = HConstant::cast(function); | 8526 HConstant* constant_function = HConstant::cast(function); |
| 8518 known_function = Handle<JSFunction>::cast(constant_function->handle()); | 8527 known_function = Handle<JSFunction>::cast(constant_function->handle()); |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8734 PrintF("\n"); | 8743 PrintF("\n"); |
| 8735 } | 8744 } |
| 8736 return; | 8745 return; |
| 8737 } | 8746 } |
| 8738 if (TryInlineCall(expr)) return; | 8747 if (TryInlineCall(expr)) return; |
| 8739 | 8748 |
| 8740 if (expr->target().is_identical_to(current_info()->closure())) { | 8749 if (expr->target().is_identical_to(current_info()->closure())) { |
| 8741 graph()->MarkRecursive(); | 8750 graph()->MarkRecursive(); |
| 8742 } | 8751 } |
| 8743 | 8752 |
| 8744 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 8753 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { |
| 8754 // When the target has a custom call IC generator, use the IC, |
| 8755 // because it is likely to generate better code. |
| 8756 HValue* context = environment()->LookupContext(); |
| 8757 call = PreProcessCall( |
| 8758 new(zone()) HCallNamed(context, var->name(), argument_count)); |
| 8759 } else { |
| 8760 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 8745 argument_count)); | 8761 argument_count)); |
| 8762 } |
| 8746 } else { | 8763 } else { |
| 8747 HValue* context = environment()->LookupContext(); | 8764 HValue* context = environment()->LookupContext(); |
| 8748 HGlobalObject* receiver = new(zone()) HGlobalObject(context); | 8765 HGlobalObject* receiver = new(zone()) HGlobalObject(context); |
| 8749 AddInstruction(receiver); | 8766 AddInstruction(receiver); |
| 8750 PushAndAdd(new(zone()) HPushArgument(receiver)); | 8767 PushAndAdd(new(zone()) HPushArgument(receiver)); |
| 8751 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 8768 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 8752 | 8769 |
| 8753 call = new(zone()) HCallGlobal(context, var->name(), argument_count); | 8770 call = new(zone()) HCallGlobal(context, var->name(), argument_count); |
| 8754 Drop(argument_count); | 8771 Drop(argument_count); |
| 8755 } | 8772 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8844 } | 8861 } |
| 8845 | 8862 |
| 8846 // Calculate instance size from initial map of constructor. | 8863 // Calculate instance size from initial map of constructor. |
| 8847 ASSERT(constructor->has_initial_map()); | 8864 ASSERT(constructor->has_initial_map()); |
| 8848 Handle<Map> initial_map(constructor->initial_map()); | 8865 Handle<Map> initial_map(constructor->initial_map()); |
| 8849 int instance_size = initial_map->instance_size(); | 8866 int instance_size = initial_map->instance_size(); |
| 8850 ASSERT(initial_map->InitialPropertiesLength() == 0); | 8867 ASSERT(initial_map->InitialPropertiesLength() == 0); |
| 8851 | 8868 |
| 8852 // Allocate an instance of the implicit receiver object. | 8869 // Allocate an instance of the implicit receiver object. |
| 8853 HValue* size_in_bytes = | 8870 HValue* size_in_bytes = |
| 8854 AddInstruction(new(zone()) HConstant(instance_size, | 8871 AddInstruction(new(zone()) HConstant(instance_size)); |
| 8855 Representation::Integer32())); | |
| 8856 | 8872 |
| 8857 HAllocate::Flags flags = HAllocate::DefaultFlags(); | 8873 HAllocate::Flags flags = HAllocate::DefaultFlags(); |
| 8858 if (FLAG_pretenuring_call_new && | 8874 if (FLAG_pretenuring_call_new && |
| 8859 isolate()->heap()->ShouldGloballyPretenure()) { | 8875 isolate()->heap()->ShouldGloballyPretenure()) { |
| 8860 flags = static_cast<HAllocate::Flags>( | 8876 flags = static_cast<HAllocate::Flags>( |
| 8861 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 8877 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
| 8862 } | 8878 } |
| 8863 | 8879 |
| 8864 HInstruction* receiver = | 8880 HInstruction* receiver = |
| 8865 AddInstruction(new(zone()) HAllocate(context, | 8881 AddInstruction(new(zone()) HAllocate(context, |
| 8866 size_in_bytes, | 8882 size_in_bytes, |
| 8867 HType::JSObject(), | 8883 HType::JSObject(), |
| 8868 flags)); | 8884 flags)); |
| 8869 HAllocate::cast(receiver)->set_known_initial_map(initial_map); | 8885 HAllocate::cast(receiver)->set_known_initial_map(initial_map); |
| 8870 | 8886 |
| 8871 // Load the initial map from the constructor. | 8887 // Load the initial map from the constructor. |
| 8872 HValue* constructor_value = | 8888 HValue* constructor_value = |
| 8873 AddInstruction(new(zone()) HConstant(constructor, | 8889 AddInstruction(new(zone()) HConstant(constructor)); |
| 8874 Representation::Tagged())); | |
| 8875 HValue* initial_map_value = | 8890 HValue* initial_map_value = |
| 8876 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( | 8891 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( |
| 8877 JSFunction::kPrototypeOrInitialMapOffset)); | 8892 JSFunction::kPrototypeOrInitialMapOffset)); |
| 8878 | 8893 |
| 8879 // Initialize map and fields of the newly allocated object. | 8894 // Initialize map and fields of the newly allocated object. |
| 8880 { NoObservableSideEffectsScope no_effects(this); | 8895 { NoObservableSideEffectsScope no_effects(this); |
| 8881 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | 8896 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); |
| 8882 AddStore(receiver, | 8897 AddStore(receiver, |
| 8883 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), | 8898 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), |
| 8884 initial_map_value); | 8899 initial_map_value); |
| 8885 HValue* empty_fixed_array = | 8900 HValue* empty_fixed_array = |
| 8886 AddInstruction(new(zone()) HConstant(factory->empty_fixed_array(), | 8901 AddInstruction(new(zone()) HConstant(factory->empty_fixed_array())); |
| 8887 Representation::Tagged())); | |
| 8888 AddStore(receiver, | 8902 AddStore(receiver, |
| 8889 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), | 8903 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), |
| 8890 empty_fixed_array); | 8904 empty_fixed_array); |
| 8891 AddStore(receiver, | 8905 AddStore(receiver, |
| 8892 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), | 8906 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), |
| 8893 empty_fixed_array); | 8907 empty_fixed_array); |
| 8894 if (initial_map->inobject_properties() != 0) { | 8908 if (initial_map->inobject_properties() != 0) { |
| 8895 HConstant* undefined = graph()->GetConstantUndefined(); | 8909 HConstant* undefined = graph()->GetConstantUndefined(); |
| 8896 for (int i = 0; i < initial_map->inobject_properties(); i++) { | 8910 for (int i = 0; i < initial_map->inobject_properties(); i++) { |
| 8897 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | 8911 int property_offset = JSObject::kHeaderSize + i * kPointerSize; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 8924 receiver->DeleteAndReplaceWith(NULL); | 8938 receiver->DeleteAndReplaceWith(NULL); |
| 8925 check->DeleteAndReplaceWith(NULL); | 8939 check->DeleteAndReplaceWith(NULL); |
| 8926 environment()->SetExpressionStackAt(receiver_index, function); | 8940 environment()->SetExpressionStackAt(receiver_index, function); |
| 8927 HInstruction* call = PreProcessCall( | 8941 HInstruction* call = PreProcessCall( |
| 8928 new(zone()) HCallNew(context, function, argument_count)); | 8942 new(zone()) HCallNew(context, function, argument_count)); |
| 8929 call->set_position(expr->position()); | 8943 call->set_position(expr->position()); |
| 8930 return ast_context()->ReturnInstruction(call, expr->id()); | 8944 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8931 } else { | 8945 } else { |
| 8932 // The constructor function is both an operand to the instruction and an | 8946 // The constructor function is both an operand to the instruction and an |
| 8933 // argument to the construct call. | 8947 // argument to the construct call. |
| 8948 Handle<JSFunction> array_function = |
| 8949 Handle<JSFunction>(isolate()->global_context()->array_function(), |
| 8950 isolate()); |
| 8934 bool use_call_new_array = FLAG_optimize_constructed_arrays && | 8951 bool use_call_new_array = FLAG_optimize_constructed_arrays && |
| 8935 !(expr->target().is_null()) && | 8952 expr->target().is_identical_to(array_function); |
| 8936 *(expr->target()) == isolate()->global_context()->array_function(); | |
| 8937 | 8953 |
| 8938 CHECK_ALIVE(VisitArgument(expr->expression())); | 8954 CHECK_ALIVE(VisitArgument(expr->expression())); |
| 8939 HValue* constructor = HPushArgument::cast(Top())->argument(); | 8955 HValue* constructor = HPushArgument::cast(Top())->argument(); |
| 8940 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 8956 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 8941 HCallNew* call; | 8957 HCallNew* call; |
| 8942 if (use_call_new_array) { | 8958 if (use_call_new_array) { |
| 8943 Handle<JSGlobalPropertyCell> cell = expr->allocation_info_cell(); | 8959 Handle<Cell> cell = expr->allocation_info_cell(); |
| 8960 AddInstruction(new(zone()) HCheckFunction(constructor, array_function)); |
| 8944 call = new(zone()) HCallNewArray(context, constructor, argument_count, | 8961 call = new(zone()) HCallNewArray(context, constructor, argument_count, |
| 8945 cell); | 8962 cell); |
| 8946 } else { | 8963 } else { |
| 8947 call = new(zone()) HCallNew(context, constructor, argument_count); | 8964 call = new(zone()) HCallNew(context, constructor, argument_count); |
| 8948 } | 8965 } |
| 8949 Drop(argument_count); | 8966 Drop(argument_count); |
| 8950 call->set_position(expr->position()); | 8967 call->set_position(expr->position()); |
| 8951 return ast_context()->ReturnInstruction(call, expr->id()); | 8968 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8952 } | 8969 } |
| 8953 } | 8970 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9072 return ast_context()->ReturnInstruction(instr, expr->id()); | 9089 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9073 } | 9090 } |
| 9074 | 9091 |
| 9075 | 9092 |
| 9076 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 9093 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
| 9077 CHECK_ALIVE(VisitForValue(expr->expression())); | 9094 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 9078 HValue* value = Pop(); | 9095 HValue* value = Pop(); |
| 9079 HValue* context = environment()->LookupContext(); | 9096 HValue* context = environment()->LookupContext(); |
| 9080 HInstruction* instr = | 9097 HInstruction* instr = |
| 9081 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); | 9098 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); |
| 9082 TypeInfo info = expr->type(); | 9099 Handle<Type> type = expr->type(); |
| 9083 Representation rep = ToRepresentation(info); | 9100 Representation rep = ToRepresentation(type); |
| 9084 if (info.IsUninitialized()) { | 9101 if (type->Is(Type::None())) { |
| 9085 AddSoftDeoptimize(); | 9102 AddSoftDeoptimize(); |
| 9086 info = TypeInfo::Unknown(); | 9103 type = handle(Type::Any(), isolate()); |
| 9087 } | 9104 } |
| 9088 if (instr->IsBinaryOperation()) { | 9105 if (instr->IsBinaryOperation()) { |
| 9089 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); | 9106 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); |
| 9090 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); | 9107 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); |
| 9091 } | 9108 } |
| 9092 return ast_context()->ReturnInstruction(instr, expr->id()); | 9109 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9093 } | 9110 } |
| 9094 | 9111 |
| 9095 | 9112 |
| 9096 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 9113 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| 9097 CHECK_ALIVE(VisitForValue(expr->expression())); | 9114 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 9098 HValue* value = Pop(); | 9115 HValue* value = Pop(); |
| 9099 TypeInfo info = expr->type(); | 9116 Handle<Type> info = expr->type(); |
| 9100 if (info.IsUninitialized()) { | 9117 if (info->Is(Type::None())) { |
| 9101 AddSoftDeoptimize(); | 9118 AddSoftDeoptimize(); |
| 9102 } | 9119 } |
| 9103 HInstruction* instr = new(zone()) HBitNot(value); | 9120 HInstruction* instr = new(zone()) HBitNot(value); |
| 9104 return ast_context()->ReturnInstruction(instr, expr->id()); | 9121 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9105 } | 9122 } |
| 9106 | 9123 |
| 9107 | 9124 |
| 9108 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 9125 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
| 9109 if (ast_context()->IsTest()) { | 9126 if (ast_context()->IsTest()) { |
| 9110 TestContext* context = TestContext::cast(ast_context()); | 9127 TestContext* context = TestContext::cast(ast_context()); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9270 | 9287 |
| 9271 if (prop->key()->IsPropertyName()) { | 9288 if (prop->key()->IsPropertyName()) { |
| 9272 // Named property. | 9289 // Named property. |
| 9273 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 9290 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 9274 | 9291 |
| 9275 CHECK_ALIVE(VisitForValue(prop->obj())); | 9292 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 9276 HValue* object = Top(); | 9293 HValue* object = Top(); |
| 9277 | 9294 |
| 9278 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 9295 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 9279 Handle<Map> map; | 9296 Handle<Map> map; |
| 9280 HInstruction* load; | 9297 HInstruction* load = NULL; |
| 9281 bool monomorphic = prop->IsMonomorphic(); | 9298 bool monomorphic = prop->IsMonomorphic(); |
| 9299 SmallMapList* types = prop->GetReceiverTypes(); |
| 9282 if (monomorphic) { | 9300 if (monomorphic) { |
| 9283 map = prop->GetReceiverTypes()->first(); | 9301 map = types->first(); |
| 9284 if (map->is_dictionary_map()) monomorphic = false; | 9302 if (map->is_dictionary_map()) monomorphic = false; |
| 9285 } | 9303 } |
| 9286 if (monomorphic) { | 9304 if (monomorphic) { |
| 9287 Handle<JSFunction> getter; | 9305 Handle<JSFunction> getter; |
| 9288 Handle<JSObject> holder; | 9306 Handle<JSObject> holder; |
| 9289 if (LookupGetter(map, name, &getter, &holder)) { | 9307 if (LookupGetter(map, name, &getter, &holder)) { |
| 9290 load = BuildCallGetter(object, map, getter, holder); | 9308 load = BuildCallGetter(object, map, getter, holder); |
| 9291 } else { | 9309 } else { |
| 9292 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 9310 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
| 9293 } | 9311 } |
| 9294 } else { | 9312 } else if (types != NULL && types->length() > 1) { |
| 9295 load = BuildLoadNamedGeneric(object, name, prop); | 9313 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
| 9296 } | 9314 } |
| 9315 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
| 9297 PushAndAdd(load); | 9316 PushAndAdd(load); |
| 9298 if (load->HasObservableSideEffects()) { | 9317 if (load->HasObservableSideEffects()) { |
| 9299 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 9318 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 9300 } | 9319 } |
| 9301 | 9320 |
| 9302 after = BuildIncrement(returns_original_input, expr); | 9321 after = BuildIncrement(returns_original_input, expr); |
| 9303 input = Pop(); | 9322 input = Pop(); |
| 9304 | 9323 |
| 9305 HInstruction* store; | 9324 HInstruction* store; |
| 9306 if (!monomorphic || map->is_observed()) { | 9325 if (!monomorphic || map->is_observed()) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9374 HValue* context, | 9393 HValue* context, |
| 9375 HValue* string, | 9394 HValue* string, |
| 9376 HValue* index) { | 9395 HValue* index) { |
| 9377 if (string->IsConstant() && index->IsConstant()) { | 9396 if (string->IsConstant() && index->IsConstant()) { |
| 9378 HConstant* c_string = HConstant::cast(string); | 9397 HConstant* c_string = HConstant::cast(string); |
| 9379 HConstant* c_index = HConstant::cast(index); | 9398 HConstant* c_index = HConstant::cast(index); |
| 9380 if (c_string->HasStringValue() && c_index->HasNumberValue()) { | 9399 if (c_string->HasStringValue() && c_index->HasNumberValue()) { |
| 9381 int32_t i = c_index->NumberValueAsInteger32(); | 9400 int32_t i = c_index->NumberValueAsInteger32(); |
| 9382 Handle<String> s = c_string->StringValue(); | 9401 Handle<String> s = c_string->StringValue(); |
| 9383 if (i < 0 || i >= s->length()) { | 9402 if (i < 0 || i >= s->length()) { |
| 9384 return new(zone()) HConstant(OS::nan_value(), Representation::Double()); | 9403 return new(zone()) HConstant(OS::nan_value()); |
| 9385 } | 9404 } |
| 9386 return new(zone()) HConstant(s->Get(i)); | 9405 return new(zone()) HConstant(s->Get(i)); |
| 9387 } | 9406 } |
| 9388 } | 9407 } |
| 9389 BuildCheckNonSmi(string); | 9408 BuildCheckNonSmi(string); |
| 9390 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 9409 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 9391 HInstruction* length = HStringLength::New(zone(), string); | 9410 HInstruction* length = HStringLength::New(zone(), string); |
| 9392 AddInstruction(length); | 9411 AddInstruction(length); |
| 9393 HInstruction* checked_index = AddBoundsCheck(index, length); | 9412 HInstruction* checked_index = AddBoundsCheck(index, length); |
| 9394 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 9413 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9450 } | 9469 } |
| 9451 return true; | 9470 return true; |
| 9452 } | 9471 } |
| 9453 | 9472 |
| 9454 | 9473 |
| 9455 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 9474 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 9456 BinaryOperation* expr, | 9475 BinaryOperation* expr, |
| 9457 HValue* left, | 9476 HValue* left, |
| 9458 HValue* right) { | 9477 HValue* right) { |
| 9459 HValue* context = environment()->LookupContext(); | 9478 HValue* context = environment()->LookupContext(); |
| 9460 TypeInfo left_info = expr->left_type(); | 9479 Handle<Type> left_type = expr->left_type(); |
| 9461 TypeInfo right_info = expr->right_type(); | 9480 Handle<Type> right_type = expr->right_type(); |
| 9462 TypeInfo result_info = expr->result_type(); | 9481 Handle<Type> result_type = expr->result_type(); |
| 9463 bool has_fixed_right_arg = expr->has_fixed_right_arg(); | 9482 bool has_fixed_right_arg = expr->has_fixed_right_arg(); |
| 9464 int fixed_right_arg_value = expr->fixed_right_arg_value(); | 9483 int fixed_right_arg_value = expr->fixed_right_arg_value(); |
| 9465 Representation left_rep = ToRepresentation(left_info); | 9484 Representation left_rep = ToRepresentation(left_type); |
| 9466 Representation right_rep = ToRepresentation(right_info); | 9485 Representation right_rep = ToRepresentation(right_type); |
| 9467 Representation result_rep = ToRepresentation(result_info); | 9486 Representation result_rep = ToRepresentation(result_type); |
| 9468 if (left_info.IsUninitialized()) { | 9487 if (left_type->Is(Type::None())) { |
| 9469 // Can't have initialized one but not the other. | |
| 9470 ASSERT(right_info.IsUninitialized()); | |
| 9471 AddSoftDeoptimize(); | 9488 AddSoftDeoptimize(); |
| 9472 left_info = right_info = TypeInfo::Unknown(); | 9489 left_type = handle(Type::Any(), isolate()); |
| 9490 } |
| 9491 if (right_type->Is(Type::None())) { |
| 9492 AddSoftDeoptimize(); |
| 9493 right_type = handle(Type::Any(), isolate()); |
| 9473 } | 9494 } |
| 9474 HInstruction* instr = NULL; | 9495 HInstruction* instr = NULL; |
| 9475 switch (expr->op()) { | 9496 switch (expr->op()) { |
| 9476 case Token::ADD: | 9497 case Token::ADD: |
| 9477 if (left_info.IsString() && right_info.IsString()) { | 9498 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { |
| 9478 BuildCheckNonSmi(left); | 9499 BuildCheckNonSmi(left); |
| 9479 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 9500 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 9480 BuildCheckNonSmi(right); | 9501 BuildCheckNonSmi(right); |
| 9481 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 9502 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 9482 instr = HStringAdd::New(zone(), context, left, right); | 9503 instr = HStringAdd::New(zone(), context, left, right); |
| 9483 } else { | 9504 } else { |
| 9484 instr = HAdd::New(zone(), context, left, right); | 9505 instr = HAdd::New(zone(), context, left, right); |
| 9485 } | 9506 } |
| 9486 break; | 9507 break; |
| 9487 case Token::SUB: | 9508 case Token::SUB: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 9500 break; | 9521 break; |
| 9501 case Token::DIV: | 9522 case Token::DIV: |
| 9502 instr = HDiv::New(zone(), context, left, right); | 9523 instr = HDiv::New(zone(), context, left, right); |
| 9503 break; | 9524 break; |
| 9504 case Token::BIT_XOR: | 9525 case Token::BIT_XOR: |
| 9505 case Token::BIT_AND: | 9526 case Token::BIT_AND: |
| 9506 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 9527 instr = HBitwise::New(zone(), expr->op(), context, left, right); |
| 9507 break; | 9528 break; |
| 9508 case Token::BIT_OR: { | 9529 case Token::BIT_OR: { |
| 9509 HValue* operand, *shift_amount; | 9530 HValue* operand, *shift_amount; |
| 9510 if (left_info.IsInteger32() && right_info.IsInteger32() && | 9531 if (left_type->Is(Type::Integer32()) && |
| 9532 right_type->Is(Type::Integer32()) && |
| 9511 MatchRotateRight(left, right, &operand, &shift_amount)) { | 9533 MatchRotateRight(left, right, &operand, &shift_amount)) { |
| 9512 instr = new(zone()) HRor(context, operand, shift_amount); | 9534 instr = new(zone()) HRor(context, operand, shift_amount); |
| 9513 } else { | 9535 } else { |
| 9514 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 9536 instr = HBitwise::New(zone(), expr->op(), context, left, right); |
| 9515 } | 9537 } |
| 9516 break; | 9538 break; |
| 9517 } | 9539 } |
| 9518 case Token::SAR: | 9540 case Token::SAR: |
| 9519 instr = HSar::New(zone(), context, left, right); | 9541 instr = HSar::New(zone(), context, left, right); |
| 9520 break; | 9542 break; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9686 CHECK_ALIVE(VisitForValue(expr->left())); | 9708 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9687 CHECK_ALIVE(VisitForValue(expr->right())); | 9709 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9688 HValue* right = Pop(); | 9710 HValue* right = Pop(); |
| 9689 HValue* left = Pop(); | 9711 HValue* left = Pop(); |
| 9690 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 9712 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| 9691 instr->set_position(expr->position()); | 9713 instr->set_position(expr->position()); |
| 9692 return ast_context()->ReturnInstruction(instr, expr->id()); | 9714 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9693 } | 9715 } |
| 9694 | 9716 |
| 9695 | 9717 |
| 9718 // TODO(rossberg): this should die eventually. |
| 9696 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { | 9719 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { |
| 9697 if (info.IsUninitialized()) return Representation::None(); | 9720 if (info.IsUninitialized()) return Representation::None(); |
| 9721 // TODO(verwaest): Return Smi rather than Integer32. |
| 9698 if (info.IsSmi()) return Representation::Integer32(); | 9722 if (info.IsSmi()) return Representation::Integer32(); |
| 9699 if (info.IsInteger32()) return Representation::Integer32(); | 9723 if (info.IsInteger32()) return Representation::Integer32(); |
| 9700 if (info.IsDouble()) return Representation::Double(); | 9724 if (info.IsDouble()) return Representation::Double(); |
| 9701 if (info.IsNumber()) return Representation::Double(); | 9725 if (info.IsNumber()) return Representation::Double(); |
| 9702 return Representation::Tagged(); | 9726 return Representation::Tagged(); |
| 9703 } | 9727 } |
| 9704 | 9728 |
| 9705 | 9729 |
| 9730 Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) { |
| 9731 if (type->Is(Type::None())) return Representation::None(); |
| 9732 if (type->Is(Type::Integer32())) return Representation::Integer32(); |
| 9733 if (type->Is(Type::Number())) return Representation::Double(); |
| 9734 return Representation::Tagged(); |
| 9735 } |
| 9736 |
| 9737 |
| 9706 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 9738 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 9707 HTypeof* typeof_expr, | 9739 HTypeof* typeof_expr, |
| 9708 Handle<String> check) { | 9740 Handle<String> check) { |
| 9709 // Note: The HTypeof itself is removed during canonicalization, if possible. | 9741 // Note: The HTypeof itself is removed during canonicalization, if possible. |
| 9710 HValue* value = typeof_expr->value(); | 9742 HValue* value = typeof_expr->value(); |
| 9711 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 9743 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
| 9712 instr->set_position(expr->position()); | 9744 instr->set_position(expr->position()); |
| 9713 return ast_context()->ReturnControl(instr, expr->id()); | 9745 return ast_context()->ReturnControl(instr, expr->id()); |
| 9714 } | 9746 } |
| 9715 | 9747 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9785 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9817 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9786 HValue* value = Pop(); | 9818 HValue* value = Pop(); |
| 9787 Literal* literal = expr->right()->AsLiteral(); | 9819 Literal* literal = expr->right()->AsLiteral(); |
| 9788 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 9820 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| 9789 HClassOfTestAndBranch* instr = | 9821 HClassOfTestAndBranch* instr = |
| 9790 new(zone()) HClassOfTestAndBranch(value, rhs); | 9822 new(zone()) HClassOfTestAndBranch(value, rhs); |
| 9791 instr->set_position(expr->position()); | 9823 instr->set_position(expr->position()); |
| 9792 return ast_context()->ReturnControl(instr, expr->id()); | 9824 return ast_context()->ReturnControl(instr, expr->id()); |
| 9793 } | 9825 } |
| 9794 | 9826 |
| 9795 TypeInfo left_type = expr->left_type(); | 9827 Handle<Type> left_type = expr->left_type(); |
| 9796 TypeInfo right_type = expr->right_type(); | 9828 Handle<Type> right_type = expr->right_type(); |
| 9797 TypeInfo overall_type = expr->overall_type(); | 9829 Handle<Type> overall_type = expr->overall_type(); |
| 9798 Representation combined_rep = ToRepresentation(overall_type); | 9830 Representation combined_rep = ToRepresentation(overall_type); |
| 9799 Representation left_rep = ToRepresentation(left_type); | 9831 Representation left_rep = ToRepresentation(left_type); |
| 9800 Representation right_rep = ToRepresentation(right_type); | 9832 Representation right_rep = ToRepresentation(right_type); |
| 9801 // Check if this expression was ever executed according to type feedback. | 9833 // Check if this expression was ever executed according to type feedback. |
| 9802 // Note that for the special typeof/null/undefined cases we get unknown here. | 9834 // Note that for the special typeof/null/undefined cases we get unknown here. |
| 9803 if (overall_type.IsUninitialized()) { | 9835 if (overall_type->Is(Type::None())) { |
| 9804 AddSoftDeoptimize(); | 9836 AddSoftDeoptimize(); |
| 9805 overall_type = left_type = right_type = TypeInfo::Unknown(); | 9837 overall_type = left_type = right_type = handle(Type::Any(), isolate()); |
| 9806 } | 9838 } |
| 9807 | 9839 |
| 9808 CHECK_ALIVE(VisitForValue(expr->left())); | 9840 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9809 CHECK_ALIVE(VisitForValue(expr->right())); | 9841 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9810 | 9842 |
| 9811 HValue* context = environment()->LookupContext(); | 9843 HValue* context = environment()->LookupContext(); |
| 9812 HValue* right = Pop(); | 9844 HValue* right = Pop(); |
| 9813 HValue* left = Pop(); | 9845 HValue* left = Pop(); |
| 9814 Token::Value op = expr->op(); | 9846 Token::Value op = expr->op(); |
| 9815 | 9847 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9867 AddInstruction(new(zone()) HCheckFunction(right, target)); | 9899 AddInstruction(new(zone()) HCheckFunction(right, target)); |
| 9868 HInstanceOfKnownGlobal* result = | 9900 HInstanceOfKnownGlobal* result = |
| 9869 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 9901 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
| 9870 result->set_position(expr->position()); | 9902 result->set_position(expr->position()); |
| 9871 return ast_context()->ReturnInstruction(result, expr->id()); | 9903 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9872 } | 9904 } |
| 9873 } else if (op == Token::IN) { | 9905 } else if (op == Token::IN) { |
| 9874 HIn* result = new(zone()) HIn(context, left, right); | 9906 HIn* result = new(zone()) HIn(context, left, right); |
| 9875 result->set_position(expr->position()); | 9907 result->set_position(expr->position()); |
| 9876 return ast_context()->ReturnInstruction(result, expr->id()); | 9908 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9877 } else if (overall_type.IsNonPrimitive()) { | 9909 } else if (overall_type->Is(Type::Receiver())) { |
| 9878 switch (op) { | 9910 switch (op) { |
| 9879 case Token::EQ: | 9911 case Token::EQ: |
| 9880 case Token::EQ_STRICT: { | 9912 case Token::EQ_STRICT: { |
| 9881 // Can we get away with map check and not instance type check? | 9913 // Can we get away with map check and not instance type check? |
| 9882 Handle<Map> map = expr->map(); | 9914 if (overall_type->IsClass()) { |
| 9883 if (!map.is_null()) { | 9915 Handle<Map> map = overall_type->AsClass(); |
| 9884 AddCheckMapsWithTransitions(left, map); | 9916 AddCheckMapsWithTransitions(left, map); |
| 9885 AddCheckMapsWithTransitions(right, map); | 9917 AddCheckMapsWithTransitions(right, map); |
| 9886 HCompareObjectEqAndBranch* result = | 9918 HCompareObjectEqAndBranch* result = |
| 9887 new(zone()) HCompareObjectEqAndBranch(left, right); | 9919 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9888 result->set_position(expr->position()); | 9920 result->set_position(expr->position()); |
| 9889 return ast_context()->ReturnControl(result, expr->id()); | 9921 return ast_context()->ReturnControl(result, expr->id()); |
| 9890 } else { | 9922 } else { |
| 9891 BuildCheckNonSmi(left); | 9923 BuildCheckNonSmi(left); |
| 9892 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 9924 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
| 9893 BuildCheckNonSmi(right); | 9925 BuildCheckNonSmi(right); |
| 9894 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 9926 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
| 9895 HCompareObjectEqAndBranch* result = | 9927 HCompareObjectEqAndBranch* result = |
| 9896 new(zone()) HCompareObjectEqAndBranch(left, right); | 9928 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9897 result->set_position(expr->position()); | 9929 result->set_position(expr->position()); |
| 9898 return ast_context()->ReturnControl(result, expr->id()); | 9930 return ast_context()->ReturnControl(result, expr->id()); |
| 9899 } | 9931 } |
| 9900 } | 9932 } |
| 9901 default: | 9933 default: |
| 9902 return Bailout("Unsupported non-primitive compare"); | 9934 return Bailout("Unsupported non-primitive compare"); |
| 9903 } | 9935 } |
| 9904 } else if (overall_type.IsInternalizedString() && | 9936 } else if (overall_type->Is(Type::InternalizedString()) && |
| 9905 Token::IsEqualityOp(op)) { | 9937 Token::IsEqualityOp(op)) { |
| 9906 BuildCheckNonSmi(left); | 9938 BuildCheckNonSmi(left); |
| 9907 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); | 9939 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); |
| 9908 BuildCheckNonSmi(right); | 9940 BuildCheckNonSmi(right); |
| 9909 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); | 9941 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); |
| 9910 HCompareObjectEqAndBranch* result = | 9942 HCompareObjectEqAndBranch* result = |
| 9911 new(zone()) HCompareObjectEqAndBranch(left, right); | 9943 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9912 result->set_position(expr->position()); | 9944 result->set_position(expr->position()); |
| 9913 return ast_context()->ReturnControl(result, expr->id()); | 9945 return ast_context()->ReturnControl(result, expr->id()); |
| 9914 } else { | 9946 } else { |
| 9915 if (combined_rep.IsTagged() || combined_rep.IsNone()) { | 9947 if (combined_rep.IsTagged() || combined_rep.IsNone()) { |
| 9916 HCompareGeneric* result = | 9948 HCompareGeneric* result = |
| 9917 new(zone()) HCompareGeneric(context, left, right, op); | 9949 new(zone()) HCompareGeneric(context, left, right, op); |
| 9918 result->set_observed_input_representation(1, left_rep); | 9950 result->set_observed_input_representation(1, left_rep); |
| 9919 result->set_observed_input_representation(2, right_rep); | 9951 result->set_observed_input_representation(2, right_rep); |
| 9920 result->set_position(expr->position()); | 9952 result->set_position(expr->position()); |
| 9921 return ast_context()->ReturnInstruction(result, expr->id()); | 9953 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9922 } else { | 9954 } else { |
| 9955 // TODO(verwaest): Remove once ToRepresentation properly returns Smi when |
| 9956 // the IC measures Smi. |
| 9957 if (left_type->Is(Type::Integer31())) left_rep = Representation::Smi(); |
| 9958 if (right_type->Is(Type::Integer31())) right_rep = Representation::Smi(); |
| 9923 HCompareIDAndBranch* result = | 9959 HCompareIDAndBranch* result = |
| 9924 new(zone()) HCompareIDAndBranch(left, right, op); | 9960 new(zone()) HCompareIDAndBranch(left, right, op); |
| 9925 result->set_observed_input_representation(left_rep, right_rep); | 9961 result->set_observed_input_representation(left_rep, right_rep); |
| 9926 result->set_position(expr->position()); | 9962 result->set_position(expr->position()); |
| 9927 return ast_context()->ReturnControl(result, expr->id()); | 9963 return ast_context()->ReturnControl(result, expr->id()); |
| 9928 } | 9964 } |
| 9929 } | 9965 } |
| 9930 } | 9966 } |
| 9931 | 9967 |
| 9932 | 9968 |
| 9933 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 9969 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 9934 HValue* value, | 9970 HValue* value, |
| 9935 NilValue nil) { | 9971 NilValue nil) { |
| 9936 ASSERT(!HasStackOverflow()); | 9972 ASSERT(!HasStackOverflow()); |
| 9937 ASSERT(current_block() != NULL); | 9973 ASSERT(current_block() != NULL); |
| 9938 ASSERT(current_block()->HasPredecessor()); | 9974 ASSERT(current_block()->HasPredecessor()); |
| 9975 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); |
| 9939 HIfContinuation continuation; | 9976 HIfContinuation continuation; |
| 9940 CompareNilICStub::Types types; | |
| 9941 if (expr->op() == Token::EQ_STRICT) { | 9977 if (expr->op() == Token::EQ_STRICT) { |
| 9942 IfBuilder if_nil(this); | 9978 IfBuilder if_nil(this); |
| 9943 if_nil.If<HCompareObjectEqAndBranch>( | 9979 if_nil.If<HCompareObjectEqAndBranch>( |
| 9944 value, (nil == kNullValue) ? graph()->GetConstantNull() | 9980 value, (nil == kNullValue) ? graph()->GetConstantNull() |
| 9945 : graph()->GetConstantUndefined()); | 9981 : graph()->GetConstantUndefined()); |
| 9946 if_nil.Then(); | 9982 if_nil.Then(); |
| 9947 if_nil.Else(); | 9983 if_nil.Else(); |
| 9948 if_nil.CaptureContinuation(&continuation); | 9984 if_nil.CaptureContinuation(&continuation); |
| 9949 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9985 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9950 } | 9986 } |
| 9951 types = CompareNilICStub::Types(expr->compare_nil_types()); | 9987 Handle<Type> type = expr->compare_nil_type()->Is(Type::None()) |
| 9952 if (types.IsEmpty()) types = CompareNilICStub::Types::FullCompare(); | 9988 ? handle(Type::Any(), isolate_) : expr->compare_nil_type(); |
| 9953 Handle<Map> map_handle = expr->map(); | 9989 BuildCompareNil(value, type, expr->position(), &continuation); |
| 9954 BuildCompareNil(value, types, map_handle, | |
| 9955 expr->position(), &continuation); | |
| 9956 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9990 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9957 } | 9991 } |
| 9958 | 9992 |
| 9959 | 9993 |
| 9960 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 9994 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 9961 // If we share optimized code between different closures, the | 9995 // If we share optimized code between different closures, the |
| 9962 // this-function is not a constant, except inside an inlined body. | 9996 // this-function is not a constant, except inside an inlined body. |
| 9963 if (function_state()->outer() != NULL) { | 9997 if (function_state()->outer() != NULL) { |
| 9964 return new(zone()) HConstant( | 9998 return new(zone()) HConstant( |
| 9965 function_state()->compilation_info()->closure(), | 9999 function_state()->compilation_info()->closure()); |
| 9966 Representation::Tagged()); | |
| 9967 } else { | 10000 } else { |
| 9968 return new(zone()) HThisFunction; | 10001 return new(zone()) HThisFunction; |
| 9969 } | 10002 } |
| 9970 } | 10003 } |
| 9971 | 10004 |
| 9972 | 10005 |
| 9973 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 10006 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| 9974 HValue* context, | 10007 HValue* context, |
| 9975 Handle<JSObject> boilerplate_object, | 10008 Handle<JSObject> boilerplate_object, |
| 9976 Handle<JSObject> original_boilerplate_object, | 10009 Handle<JSObject> original_boilerplate_object, |
| 9977 int data_size, | 10010 int data_size, |
| 9978 int pointer_size, | 10011 int pointer_size, |
| 9979 AllocationSiteMode mode) { | 10012 AllocationSiteMode mode) { |
| 9980 Zone* zone = this->zone(); | 10013 Zone* zone = this->zone(); |
| 9981 int total_size = data_size + pointer_size; | 10014 int total_size = data_size + pointer_size; |
| 9982 | 10015 |
| 9983 NoObservableSideEffectsScope no_effects(this); | 10016 NoObservableSideEffectsScope no_effects(this); |
| 9984 | 10017 |
| 9985 HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE; | 10018 HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE; |
| 9986 // TODO(hpayer): add support for old data space | 10019 // TODO(hpayer): add support for old data space |
| 9987 if (isolate()->heap()->ShouldGloballyPretenure() && | 10020 if (isolate()->heap()->ShouldGloballyPretenure() && |
| 9988 data_size == 0) { | 10021 data_size == 0) { |
| 9989 flags = static_cast<HAllocate::Flags>( | 10022 flags = static_cast<HAllocate::Flags>( |
| 9990 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 10023 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
| 9991 } | 10024 } |
| 9992 | 10025 |
| 9993 HValue* size_in_bytes = | 10026 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(total_size)); |
| 9994 AddInstruction(new(zone) HConstant(total_size, | |
| 9995 Representation::Integer32())); | |
| 9996 HInstruction* result = | 10027 HInstruction* result = |
| 9997 AddInstruction(new(zone) HAllocate(context, | 10028 AddInstruction(new(zone) HAllocate(context, |
| 9998 size_in_bytes, | 10029 size_in_bytes, |
| 9999 HType::JSObject(), | 10030 HType::JSObject(), |
| 10000 flags)); | 10031 flags)); |
| 10001 int offset = 0; | 10032 int offset = 0; |
| 10002 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, result, | 10033 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, result, |
| 10003 &offset, mode); | 10034 &offset, mode); |
| 10004 return result; | 10035 return result; |
| 10005 } | 10036 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10042 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | 10073 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); |
| 10043 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, | 10074 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, |
| 10044 object_properties, target, offset); | 10075 object_properties, target, offset); |
| 10045 | 10076 |
| 10046 // Create allocation site info. | 10077 // Create allocation site info. |
| 10047 if (mode == TRACK_ALLOCATION_SITE && | 10078 if (mode == TRACK_ALLOCATION_SITE && |
| 10048 boilerplate_object->map()->CanTrackAllocationSite()) { | 10079 boilerplate_object->map()->CanTrackAllocationSite()) { |
| 10049 elements_offset += AllocationSiteInfo::kSize; | 10080 elements_offset += AllocationSiteInfo::kSize; |
| 10050 *offset += AllocationSiteInfo::kSize; | 10081 *offset += AllocationSiteInfo::kSize; |
| 10051 HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant( | 10082 HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant( |
| 10052 original_boilerplate_object, Representation::Tagged())); | 10083 original_boilerplate_object)); |
| 10053 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); | 10084 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); |
| 10054 } | 10085 } |
| 10055 } | 10086 } |
| 10056 | 10087 |
| 10057 | 10088 |
| 10058 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( | 10089 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( |
| 10059 Handle<JSObject> boilerplate_object, | 10090 Handle<JSObject> boilerplate_object, |
| 10060 HInstruction* target, | 10091 HInstruction* target, |
| 10061 int object_offset, | 10092 int object_offset, |
| 10062 int elements_offset, | 10093 int elements_offset, |
| 10063 int elements_size) { | 10094 int elements_size) { |
| 10064 ASSERT(boilerplate_object->properties()->length() == 0); | 10095 ASSERT(boilerplate_object->properties()->length() == 0); |
| 10065 Zone* zone = this->zone(); | 10096 Zone* zone = this->zone(); |
| 10066 HValue* result = NULL; | 10097 HValue* result = NULL; |
| 10067 | 10098 |
| 10068 HValue* object_header = | 10099 HValue* object_header = |
| 10069 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | 10100 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); |
| 10070 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 10101 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
| 10071 AddStoreMapConstant(object_header, boilerplate_object_map); | 10102 AddStoreMapConstant(object_header, boilerplate_object_map); |
| 10072 | 10103 |
| 10073 HInstruction* elements; | 10104 HInstruction* elements; |
| 10074 if (elements_size == 0) { | 10105 if (elements_size == 0) { |
| 10075 Handle<Object> elements_field = | 10106 Handle<Object> elements_field = |
| 10076 Handle<Object>(boilerplate_object->elements(), isolate()); | 10107 Handle<Object>(boilerplate_object->elements(), isolate()); |
| 10077 elements = AddInstruction(new(zone) HConstant( | 10108 elements = AddInstruction(new(zone) HConstant(elements_field)); |
| 10078 elements_field, Representation::Tagged())); | |
| 10079 } else { | 10109 } else { |
| 10080 elements = AddInstruction(new(zone) HInnerAllocatedObject( | 10110 elements = AddInstruction(new(zone) HInnerAllocatedObject( |
| 10081 target, elements_offset)); | 10111 target, elements_offset)); |
| 10082 result = elements; | 10112 result = elements; |
| 10083 } | 10113 } |
| 10084 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); | 10114 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); |
| 10085 | 10115 |
| 10086 Handle<Object> properties_field = | 10116 Handle<Object> properties_field = |
| 10087 Handle<Object>(boilerplate_object->properties(), isolate()); | 10117 Handle<Object>(boilerplate_object->properties(), isolate()); |
| 10088 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 10118 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
| 10089 HInstruction* properties = AddInstruction(new(zone) HConstant( | 10119 HInstruction* properties = AddInstruction(new(zone) HConstant( |
| 10090 properties_field, Representation::None())); | 10120 properties_field)); |
| 10091 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 10121 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 10092 AddStore(object_header, access, properties); | 10122 AddStore(object_header, access, properties); |
| 10093 | 10123 |
| 10094 if (boilerplate_object->IsJSArray()) { | 10124 if (boilerplate_object->IsJSArray()) { |
| 10095 Handle<JSArray> boilerplate_array = | 10125 Handle<JSArray> boilerplate_array = |
| 10096 Handle<JSArray>::cast(boilerplate_object); | 10126 Handle<JSArray>::cast(boilerplate_object); |
| 10097 Handle<Object> length_field = | 10127 Handle<Object> length_field = |
| 10098 Handle<Object>(boilerplate_array->length(), isolate()); | 10128 Handle<Object>(boilerplate_array->length(), isolate()); |
| 10099 HInstruction* length = AddInstruction(new(zone) HConstant( | 10129 HInstruction* length = AddInstruction(new(zone) HConstant(length_field)); |
| 10100 length_field, Representation::None())); | |
| 10101 | 10130 |
| 10102 ASSERT(boilerplate_array->length()->IsSmi()); | 10131 ASSERT(boilerplate_array->length()->IsSmi()); |
| 10103 Representation representation = | 10132 Representation representation = |
| 10104 IsFastElementsKind(boilerplate_array->GetElementsKind()) | 10133 IsFastElementsKind(boilerplate_array->GetElementsKind()) |
| 10105 ? Representation::Smi() : Representation::Tagged(); | 10134 ? Representation::Smi() : Representation::Tagged(); |
| 10106 AddStore(object_header, HObjectAccess::ForArrayLength(), | 10135 AddStore(object_header, HObjectAccess::ForArrayLength(), |
| 10107 length, representation); | 10136 length, representation); |
| 10108 } | 10137 } |
| 10109 | 10138 |
| 10110 return result; | 10139 return result; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10146 isolate())); | 10175 isolate())); |
| 10147 HInstruction* value_instruction = | 10176 HInstruction* value_instruction = |
| 10148 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10177 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); |
| 10149 | 10178 |
| 10150 AddStore(object_properties, access, value_instruction); | 10179 AddStore(object_properties, access, value_instruction); |
| 10151 | 10180 |
| 10152 BuildEmitDeepCopy(value_object, original_value_object, target, | 10181 BuildEmitDeepCopy(value_object, original_value_object, target, |
| 10153 offset, DONT_TRACK_ALLOCATION_SITE); | 10182 offset, DONT_TRACK_ALLOCATION_SITE); |
| 10154 } else { | 10183 } else { |
| 10155 Representation representation = details.representation(); | 10184 Representation representation = details.representation(); |
| 10156 HInstruction* value_instruction = AddInstruction(new(zone) HConstant( | 10185 HInstruction* value_instruction = |
| 10157 value, Representation::Tagged())); | 10186 AddInstruction(new(zone) HConstant(value)); |
| 10158 | 10187 |
| 10159 if (representation.IsDouble()) { | 10188 if (representation.IsDouble()) { |
| 10160 // Allocate a HeapNumber box and store the value into it. | 10189 // Allocate a HeapNumber box and store the value into it. |
| 10161 HInstruction* double_box = | 10190 HInstruction* double_box = |
| 10162 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10191 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); |
| 10163 AddStoreMapConstant(double_box, | 10192 AddStoreMapConstant(double_box, |
| 10164 isolate()->factory()->heap_number_map()); | 10193 isolate()->factory()->heap_number_map()); |
| 10165 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 10194 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
| 10166 value_instruction, Representation::Double()); | 10195 value_instruction, Representation::Double()); |
| 10167 value_instruction = double_box; | 10196 value_instruction = double_box; |
| 10168 *offset += HeapNumber::kSize; | 10197 *offset += HeapNumber::kSize; |
| 10169 } | 10198 } |
| 10170 | 10199 |
| 10171 AddStore(object_properties, access, value_instruction); | 10200 AddStore(object_properties, access, value_instruction); |
| 10172 } | 10201 } |
| 10173 } | 10202 } |
| 10174 | 10203 |
| 10175 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 10204 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
| 10176 HInstruction* value_instruction = AddInstruction(new(zone) | 10205 HInstruction* value_instruction = AddInstruction(new(zone) |
| 10177 HConstant(isolate()->factory()->one_pointer_filler_map(), | 10206 HConstant(isolate()->factory()->one_pointer_filler_map())); |
| 10178 Representation::Tagged())); | |
| 10179 for (int i = copied_fields; i < inobject_properties; i++) { | 10207 for (int i = copied_fields; i < inobject_properties; i++) { |
| 10180 ASSERT(boilerplate_object->IsJSObject()); | 10208 ASSERT(boilerplate_object->IsJSObject()); |
| 10181 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 10209 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
| 10182 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 10210 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
| 10183 AddStore(object_properties, access, value_instruction); | 10211 AddStore(object_properties, access, value_instruction); |
| 10184 } | 10212 } |
| 10185 } | 10213 } |
| 10186 | 10214 |
| 10187 | 10215 |
| 10188 void HOptimizedGraphBuilder::BuildEmitElements( | 10216 void HOptimizedGraphBuilder::BuildEmitElements( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 10210 UNREACHABLE(); | 10238 UNREACHABLE(); |
| 10211 } | 10239 } |
| 10212 } | 10240 } |
| 10213 | 10241 |
| 10214 | 10242 |
| 10215 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( | 10243 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( |
| 10216 Handle<FixedArrayBase> elements, | 10244 Handle<FixedArrayBase> elements, |
| 10217 ElementsKind kind, | 10245 ElementsKind kind, |
| 10218 HValue* object_elements) { | 10246 HValue* object_elements) { |
| 10219 Zone* zone = this->zone(); | 10247 Zone* zone = this->zone(); |
| 10220 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( | 10248 HInstruction* boilerplate_elements = |
| 10221 elements, Representation::Tagged())); | 10249 AddInstruction(new(zone) HConstant(elements)); |
| 10222 int elements_length = elements->length(); | 10250 int elements_length = elements->length(); |
| 10223 for (int i = 0; i < elements_length; i++) { | 10251 for (int i = 0; i < elements_length; i++) { |
| 10224 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); | 10252 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); |
| 10225 HInstruction* value_instruction = | 10253 HInstruction* value_instruction = |
| 10226 AddInstruction(new(zone) HLoadKeyed( | 10254 AddInstruction(new(zone) HLoadKeyed( |
| 10227 boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE)); | 10255 boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE)); |
| 10228 HInstruction* store = AddInstruction(new(zone) HStoreKeyed( | 10256 HInstruction* store = AddInstruction(new(zone) HStoreKeyed( |
| 10229 object_elements, key_constant, value_instruction, kind)); | 10257 object_elements, key_constant, value_instruction, kind)); |
| 10230 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 10258 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 10231 } | 10259 } |
| 10232 } | 10260 } |
| 10233 | 10261 |
| 10234 | 10262 |
| 10235 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 10263 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| 10236 Handle<FixedArrayBase> elements, | 10264 Handle<FixedArrayBase> elements, |
| 10237 Handle<FixedArrayBase> original_elements, | 10265 Handle<FixedArrayBase> original_elements, |
| 10238 ElementsKind kind, | 10266 ElementsKind kind, |
| 10239 HValue* object_elements, | 10267 HValue* object_elements, |
| 10240 HInstruction* target, | 10268 HInstruction* target, |
| 10241 int* offset) { | 10269 int* offset) { |
| 10242 Zone* zone = this->zone(); | 10270 Zone* zone = this->zone(); |
| 10243 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( | 10271 HInstruction* boilerplate_elements = |
| 10244 elements, Representation::Tagged())); | 10272 AddInstruction(new(zone) HConstant(elements)); |
| 10245 int elements_length = elements->length(); | 10273 int elements_length = elements->length(); |
| 10246 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 10274 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 10247 Handle<FixedArray> original_fast_elements = | 10275 Handle<FixedArray> original_fast_elements = |
| 10248 Handle<FixedArray>::cast(original_elements); | 10276 Handle<FixedArray>::cast(original_elements); |
| 10249 for (int i = 0; i < elements_length; i++) { | 10277 for (int i = 0; i < elements_length; i++) { |
| 10250 Handle<Object> value(fast_elements->get(i), isolate()); | 10278 Handle<Object> value(fast_elements->get(i), isolate()); |
| 10251 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); | 10279 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); |
| 10252 if (value->IsJSObject()) { | 10280 if (value->IsJSObject()) { |
| 10253 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 10281 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10254 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 10282 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| (...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11003 | 11031 |
| 11004 HEnvironment::HEnvironment(HEnvironment* outer, | 11032 HEnvironment::HEnvironment(HEnvironment* outer, |
| 11005 Handle<JSFunction> closure, | 11033 Handle<JSFunction> closure, |
| 11006 FrameType frame_type, | 11034 FrameType frame_type, |
| 11007 int arguments, | 11035 int arguments, |
| 11008 Zone* zone) | 11036 Zone* zone) |
| 11009 : closure_(closure), | 11037 : closure_(closure), |
| 11010 values_(arguments, zone), | 11038 values_(arguments, zone), |
| 11011 frame_type_(frame_type), | 11039 frame_type_(frame_type), |
| 11012 parameter_count_(arguments), | 11040 parameter_count_(arguments), |
| 11041 specials_count_(0), |
| 11013 local_count_(0), | 11042 local_count_(0), |
| 11014 outer_(outer), | 11043 outer_(outer), |
| 11015 entry_(NULL), | 11044 entry_(NULL), |
| 11016 pop_count_(0), | 11045 pop_count_(0), |
| 11017 push_count_(0), | 11046 push_count_(0), |
| 11018 ast_id_(BailoutId::None()), | 11047 ast_id_(BailoutId::None()), |
| 11019 zone_(zone) { | 11048 zone_(zone) { |
| 11020 } | 11049 } |
| 11021 | 11050 |
| 11022 | 11051 |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11549 names_.Add(name); | 11578 names_.Add(name); |
| 11550 timing_.Add(ticks); | 11579 timing_.Add(ticks); |
| 11551 sizes_.Add(size); | 11580 sizes_.Add(size); |
| 11552 } | 11581 } |
| 11553 } | 11582 } |
| 11554 | 11583 |
| 11555 | 11584 |
| 11556 const char* const HPhase::kFullCodeGen = "Full code generator"; | 11585 const char* const HPhase::kFullCodeGen = "Full code generator"; |
| 11557 | 11586 |
| 11558 | 11587 |
| 11559 HPhase::HPhase(const char* name, Isolate* isolate) { | 11588 HPhase::HPhase(const char* name, Isolate* isolate, Zone* zone) { |
| 11560 Init(isolate, name, NULL, NULL, NULL); | 11589 Init(isolate, name, zone, NULL, NULL, NULL); |
| 11561 } | 11590 } |
| 11562 | 11591 |
| 11563 | 11592 |
| 11564 HPhase::HPhase(const char* name, HGraph* graph) { | 11593 HPhase::HPhase(const char* name, HGraph* graph) { |
| 11565 Init(graph->isolate(), name, graph, NULL, NULL); | 11594 Init(graph->isolate(), name, graph->zone(), graph, NULL, NULL); |
| 11566 } | 11595 } |
| 11567 | 11596 |
| 11568 | 11597 |
| 11569 HPhase::HPhase(const char* name, LChunk* chunk) { | 11598 HPhase::HPhase(const char* name, LChunk* chunk) { |
| 11570 Init(chunk->isolate(), name, NULL, chunk, NULL); | 11599 Init(chunk->isolate(), name, chunk->zone(), NULL, chunk, NULL); |
| 11571 } | 11600 } |
| 11572 | 11601 |
| 11573 | 11602 |
| 11574 HPhase::HPhase(const char* name, LAllocator* allocator) { | 11603 HPhase::HPhase(const char* name, LAllocator* allocator) { |
| 11575 Init(allocator->isolate(), name, NULL, NULL, allocator); | 11604 Init(allocator->isolate(), name, allocator->zone(), NULL, NULL, allocator); |
| 11576 } | 11605 } |
| 11577 | 11606 |
| 11578 | 11607 |
| 11579 void HPhase::Init(Isolate* isolate, | 11608 void HPhase::Init(Isolate* isolate, |
| 11580 const char* name, | 11609 const char* name, |
| 11610 Zone* zone, |
| 11581 HGraph* graph, | 11611 HGraph* graph, |
| 11582 LChunk* chunk, | 11612 LChunk* chunk, |
| 11583 LAllocator* allocator) { | 11613 LAllocator* allocator) { |
| 11584 isolate_ = isolate; | 11614 isolate_ = isolate; |
| 11585 name_ = name; | 11615 name_ = name; |
| 11616 zone_ = zone; |
| 11586 graph_ = graph; | 11617 graph_ = graph; |
| 11587 chunk_ = chunk; | 11618 chunk_ = chunk; |
| 11588 allocator_ = allocator; | 11619 allocator_ = allocator; |
| 11589 if (allocator != NULL && chunk_ == NULL) { | 11620 if (allocator != NULL && chunk_ == NULL) { |
| 11590 chunk_ = allocator->chunk(); | 11621 chunk_ = allocator->chunk(); |
| 11591 } | 11622 } |
| 11592 if (FLAG_hydrogen_stats) { | 11623 if (FLAG_hydrogen_stats) { |
| 11593 start_ticks_ = OS::Ticks(); | 11624 start_ticks_ = OS::Ticks(); |
| 11594 start_allocation_size_ = Zone::allocation_size_; | 11625 start_allocation_size_ = zone_->allocation_size(); |
| 11595 } | 11626 } |
| 11596 } | 11627 } |
| 11597 | 11628 |
| 11598 | 11629 |
| 11599 HPhase::~HPhase() { | 11630 HPhase::~HPhase() { |
| 11600 if (FLAG_hydrogen_stats) { | 11631 if (FLAG_hydrogen_stats) { |
| 11601 int64_t ticks = OS::Ticks() - start_ticks_; | 11632 int64_t ticks = OS::Ticks() - start_ticks_; |
| 11602 unsigned size = Zone::allocation_size_ - start_allocation_size_; | 11633 unsigned size = zone_->allocation_size() - start_allocation_size_; |
| 11603 isolate_->GetHStatistics()->SaveTiming(name_, ticks, size); | 11634 isolate_->GetHStatistics()->SaveTiming(name_, ticks, size); |
| 11604 } | 11635 } |
| 11605 | 11636 |
| 11606 // Produce trace output if flag is set so that the first letter of the | 11637 // Produce trace output if flag is set so that the first letter of the |
| 11607 // phase name matches the command line parameter FLAG_trace_phase. | 11638 // phase name matches the command line parameter FLAG_trace_phase. |
| 11608 if (FLAG_trace_hydrogen && | 11639 if (FLAG_trace_hydrogen && |
| 11609 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL) { | 11640 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL) { |
| 11610 if (graph_ != NULL) { | 11641 if (graph_ != NULL) { |
| 11611 isolate_->GetHTracer()->TraceHydrogen(name_, graph_); | 11642 isolate_->GetHTracer()->TraceHydrogen(name_, graph_); |
| 11612 } | 11643 } |
| 11613 if (chunk_ != NULL) { | 11644 if (chunk_ != NULL) { |
| 11614 isolate_->GetHTracer()->TraceLithium(name_, chunk_); | 11645 isolate_->GetHTracer()->TraceLithium(name_, chunk_); |
| 11615 } | 11646 } |
| 11616 if (allocator_ != NULL) { | 11647 if (allocator_ != NULL) { |
| 11617 isolate_->GetHTracer()->TraceLiveRanges(name_, allocator_); | 11648 isolate_->GetHTracer()->TraceLiveRanges(name_, allocator_); |
| 11618 } | 11649 } |
| 11619 } | 11650 } |
| 11620 | 11651 |
| 11621 #ifdef DEBUG | 11652 #ifdef DEBUG |
| 11622 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11653 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11623 if (allocator_ != NULL) allocator_->Verify(); | 11654 if (allocator_ != NULL) allocator_->Verify(); |
| 11624 #endif | 11655 #endif |
| 11625 } | 11656 } |
| 11626 | 11657 |
| 11627 } } // namespace v8::internal | 11658 } } // namespace v8::internal |
| OLD | NEW |