| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 #include "hydrogen-minus-zero.h" | 51 #include "hydrogen-minus-zero.h" |
| 52 #include "hydrogen-osr.h" | 52 #include "hydrogen-osr.h" |
| 53 #include "hydrogen-range-analysis.h" | 53 #include "hydrogen-range-analysis.h" |
| 54 #include "hydrogen-redundant-phi.h" | 54 #include "hydrogen-redundant-phi.h" |
| 55 #include "hydrogen-removable-simulates.h" | 55 #include "hydrogen-removable-simulates.h" |
| 56 #include "hydrogen-representation-changes.h" | 56 #include "hydrogen-representation-changes.h" |
| 57 #include "hydrogen-sce.h" | 57 #include "hydrogen-sce.h" |
| 58 #include "hydrogen-uint32-analysis.h" | 58 #include "hydrogen-uint32-analysis.h" |
| 59 #include "lithium-allocator.h" | 59 #include "lithium-allocator.h" |
| 60 #include "parser.h" | 60 #include "parser.h" |
| 61 #include "runtime.h" |
| 61 #include "scopeinfo.h" | 62 #include "scopeinfo.h" |
| 62 #include "scopes.h" | 63 #include "scopes.h" |
| 63 #include "stub-cache.h" | 64 #include "stub-cache.h" |
| 64 #include "typing.h" | 65 #include "typing.h" |
| 65 | 66 |
| 66 #if V8_TARGET_ARCH_IA32 | 67 #if V8_TARGET_ARCH_IA32 |
| 67 #include "ia32/lithium-codegen-ia32.h" | 68 #include "ia32/lithium-codegen-ia32.h" |
| 68 #elif V8_TARGET_ARCH_X64 | 69 #elif V8_TARGET_ARCH_X64 |
| 69 #include "x64/lithium-codegen-x64.h" | 70 #include "x64/lithium-codegen-x64.h" |
| 70 #elif V8_TARGET_ARCH_ARM | 71 #elif V8_TARGET_ARCH_ARM |
| (...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1188 set_current_block(NULL); | 1189 set_current_block(NULL); |
| 1189 } | 1190 } |
| 1190 } | 1191 } |
| 1191 | 1192 |
| 1192 | 1193 |
| 1193 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { | 1194 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { |
| 1194 if (FLAG_native_code_counters && counter->Enabled()) { | 1195 if (FLAG_native_code_counters && counter->Enabled()) { |
| 1195 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 1196 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
| 1196 HValue* old_value = Add<HLoadNamedField>(reference, | 1197 HValue* old_value = Add<HLoadNamedField>(reference, |
| 1197 HObjectAccess::ForCounter()); | 1198 HObjectAccess::ForCounter()); |
| 1198 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); | 1199 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1()); |
| 1199 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 1200 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
| 1200 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), | 1201 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), |
| 1201 new_value); | 1202 new_value); |
| 1202 } | 1203 } |
| 1203 } | 1204 } |
| 1204 | 1205 |
| 1205 | 1206 |
| 1206 void HGraphBuilder::AddSimulate(BailoutId id, | 1207 void HGraphBuilder::AddSimulate(BailoutId id, |
| 1207 RemovableSimulate removable) { | 1208 RemovableSimulate removable) { |
| 1208 ASSERT(current_block() != NULL); | 1209 ASSERT(current_block() != NULL); |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 HValue* elements = AddLoadElements(receiver); | 1533 HValue* elements = AddLoadElements(receiver); |
| 1533 | 1534 |
| 1534 HValue* hash = BuildElementIndexHash(key); | 1535 HValue* hash = BuildElementIndexHash(key); |
| 1535 | 1536 |
| 1536 HValue* capacity = Add<HLoadKeyed>( | 1537 HValue* capacity = Add<HLoadKeyed>( |
| 1537 elements, | 1538 elements, |
| 1538 Add<HConstant>(NameDictionary::kCapacityIndex), | 1539 Add<HConstant>(NameDictionary::kCapacityIndex), |
| 1539 static_cast<HValue*>(NULL), | 1540 static_cast<HValue*>(NULL), |
| 1540 FAST_SMI_ELEMENTS); | 1541 FAST_SMI_ELEMENTS); |
| 1541 | 1542 |
| 1542 HValue* mask = Add<HSub>(capacity, graph()->GetConstant1()); | 1543 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); |
| 1543 mask->ChangeRepresentation(Representation::Integer32()); | 1544 mask->ChangeRepresentation(Representation::Integer32()); |
| 1544 mask->ClearFlag(HValue::kCanOverflow); | 1545 mask->ClearFlag(HValue::kCanOverflow); |
| 1545 | 1546 |
| 1546 return BuildUncheckedDictionaryElementLoadHelper(elements, key, | 1547 return BuildUncheckedDictionaryElementLoadHelper(elements, key, |
| 1547 hash, mask, 0); | 1548 hash, mask, 0); |
| 1548 } | 1549 } |
| 1549 | 1550 |
| 1550 | 1551 |
| 1551 HValue* HGraphBuilder::BuildNumberToString(HValue* object, | 1552 HValue* HGraphBuilder::BuildNumberToString(HValue* object, |
| 1552 Handle<Type> type) { | 1553 Handle<Type> type) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1564 graph()->CreateBasicBlock()); | 1565 graph()->CreateBasicBlock()); |
| 1565 | 1566 |
| 1566 // Load the number string cache. | 1567 // Load the number string cache. |
| 1567 HValue* number_string_cache = | 1568 HValue* number_string_cache = |
| 1568 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); | 1569 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); |
| 1569 | 1570 |
| 1570 // Make the hash mask from the length of the number string cache. It | 1571 // Make the hash mask from the length of the number string cache. It |
| 1571 // contains two elements (number and string) for each cache entry. | 1572 // contains two elements (number and string) for each cache entry. |
| 1572 HValue* mask = AddLoadFixedArrayLength(number_string_cache); | 1573 HValue* mask = AddLoadFixedArrayLength(number_string_cache); |
| 1573 mask->set_type(HType::Smi()); | 1574 mask->set_type(HType::Smi()); |
| 1574 mask = Add<HSar>(mask, graph()->GetConstant1()); | 1575 mask = AddUncasted<HSar>(mask, graph()->GetConstant1()); |
| 1575 mask = Add<HSub>(mask, graph()->GetConstant1()); | 1576 mask = AddUncasted<HSub>(mask, graph()->GetConstant1()); |
| 1576 | 1577 |
| 1577 // Check whether object is a smi. | 1578 // Check whether object is a smi. |
| 1578 IfBuilder if_objectissmi(this); | 1579 IfBuilder if_objectissmi(this); |
| 1579 if_objectissmi.If<HIsSmiAndBranch>(object); | 1580 if_objectissmi.If<HIsSmiAndBranch>(object); |
| 1580 if_objectissmi.Then(); | 1581 if_objectissmi.Then(); |
| 1581 { | 1582 { |
| 1582 // Compute hash for smi similar to smi_get_hash(). | 1583 // Compute hash for smi similar to smi_get_hash(). |
| 1583 HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask); | 1584 HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask); |
| 1584 | 1585 |
| 1585 // Load the key. | 1586 // Load the key. |
| 1586 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1()); | 1587 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1()); |
| 1587 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, | 1588 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, |
| 1588 static_cast<HValue*>(NULL), | 1589 static_cast<HValue*>(NULL), |
| 1589 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 1590 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 1590 | 1591 |
| 1591 // Check if object == key. | 1592 // Check if object == key. |
| 1592 IfBuilder if_objectiskey(this); | 1593 IfBuilder if_objectiskey(this); |
| 1593 if_objectiskey.If<HCompareObjectEqAndBranch>(object, key); | 1594 if_objectiskey.If<HCompareObjectEqAndBranch>(object, key); |
| 1594 if_objectiskey.Then(); | 1595 if_objectiskey.Then(); |
| 1595 { | 1596 { |
| 1596 // Make the key_index available. | 1597 // Make the key_index available. |
| 1597 Push(key_index); | 1598 Push(key_index); |
| 1598 } | 1599 } |
| 1599 if_objectiskey.JoinContinuation(&found); | 1600 if_objectiskey.JoinContinuation(&found); |
| 1600 } | 1601 } |
| 1601 if_objectissmi.Else(); | 1602 if_objectissmi.Else(); |
| 1602 { | 1603 { |
| 1603 if (type->Is(Type::Smi())) { | 1604 if (type->Is(Type::Smi())) { |
| 1604 if_objectissmi.Deopt("Excepted smi"); | 1605 if_objectissmi.Deopt("Expected smi"); |
| 1605 } else { | 1606 } else { |
| 1606 // Check if the object is a heap number. | 1607 // Check if the object is a heap number. |
| 1607 IfBuilder if_objectisnumber(this); | 1608 IfBuilder if_objectisnumber(this); |
| 1608 if_objectisnumber.If<HCompareMap>( | 1609 if_objectisnumber.If<HCompareMap>( |
| 1609 object, isolate()->factory()->heap_number_map()); | 1610 object, isolate()->factory()->heap_number_map()); |
| 1610 if_objectisnumber.Then(); | 1611 if_objectisnumber.Then(); |
| 1611 { | 1612 { |
| 1612 // Compute hash for heap number similar to double_get_hash(). | 1613 // Compute hash for heap number similar to double_get_hash(). |
| 1613 HValue* low = Add<HLoadNamedField>( | 1614 HValue* low = Add<HLoadNamedField>( |
| 1614 object, HObjectAccess::ForHeapNumberValueLowestBits()); | 1615 object, HObjectAccess::ForHeapNumberValueLowestBits()); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1709 HValue* dst, | 1710 HValue* dst, |
| 1710 HValue* dst_offset, | 1711 HValue* dst_offset, |
| 1711 String::Encoding dst_encoding, | 1712 String::Encoding dst_encoding, |
| 1712 HValue* length) { | 1713 HValue* length) { |
| 1713 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || | 1714 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || |
| 1714 src_encoding == String::ONE_BYTE_ENCODING); | 1715 src_encoding == String::ONE_BYTE_ENCODING); |
| 1715 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); | 1716 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
| 1716 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1717 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); |
| 1717 { | 1718 { |
| 1718 HValue* src_index = AddUncasted<HAdd>(src_offset, index); | 1719 HValue* src_index = AddUncasted<HAdd>(src_offset, index); |
| 1719 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index); | 1720 HValue* value = |
| 1721 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); |
| 1720 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); | 1722 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); |
| 1721 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); | 1723 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); |
| 1722 } | 1724 } |
| 1723 loop.EndBody(); | 1725 loop.EndBody(); |
| 1724 } | 1726 } |
| 1725 | 1727 |
| 1726 | 1728 |
| 1727 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, | 1729 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, |
| 1728 HValue* right, | 1730 HValue* right, |
| 1729 PretenureFlag pretenure_flag) { | 1731 PretenureFlag pretenure_flag) { |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2228 | 2230 |
| 2229 HConstant* empty_fixed_array = | 2231 HConstant* empty_fixed_array = |
| 2230 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 2232 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
| 2231 | 2233 |
| 2232 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 2234 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 2233 Add<HStoreNamedField>(array, access, empty_fixed_array); | 2235 Add<HStoreNamedField>(array, access, empty_fixed_array); |
| 2234 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), | 2236 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), |
| 2235 length_field); | 2237 length_field); |
| 2236 | 2238 |
| 2237 if (mode == TRACK_ALLOCATION_SITE) { | 2239 if (mode == TRACK_ALLOCATION_SITE) { |
| 2238 BuildCreateAllocationMemento(array, | 2240 BuildCreateAllocationMemento( |
| 2239 JSArray::kSize, | 2241 array, Add<HConstant>(JSArray::kSize), allocation_site_payload); |
| 2240 allocation_site_payload); | |
| 2241 } | 2242 } |
| 2242 | 2243 |
| 2243 int elements_location = JSArray::kSize; | 2244 int elements_location = JSArray::kSize; |
| 2244 if (mode == TRACK_ALLOCATION_SITE) { | 2245 if (mode == TRACK_ALLOCATION_SITE) { |
| 2245 elements_location += AllocationMemento::kSize; | 2246 elements_location += AllocationMemento::kSize; |
| 2246 } | 2247 } |
| 2247 | 2248 |
| 2248 HValue* elements = Add<HInnerAllocatedObject>(array, elements_location); | 2249 HInnerAllocatedObject* elements = Add<HInnerAllocatedObject>( |
| 2250 array, Add<HConstant>(elements_location)); |
| 2249 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); | 2251 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); |
| 2250 return static_cast<HInnerAllocatedObject*>(elements); | 2252 return elements; |
| 2251 } | 2253 } |
| 2252 | 2254 |
| 2253 | 2255 |
| 2254 HInstruction* HGraphBuilder::AddElementAccess( | 2256 HInstruction* HGraphBuilder::AddElementAccess( |
| 2255 HValue* elements, | 2257 HValue* elements, |
| 2256 HValue* checked_key, | 2258 HValue* checked_key, |
| 2257 HValue* val, | 2259 HValue* val, |
| 2258 HValue* dependency, | 2260 HValue* dependency, |
| 2259 ElementsKind elements_kind, | 2261 ElementsKind elements_kind, |
| 2260 bool is_store, | 2262 bool is_store, |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2470 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 2472 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 2471 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 2473 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 2472 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 2474 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
| 2473 Add<HStoreNamedField>(object, access, | 2475 Add<HStoreNamedField>(object, access, |
| 2474 Add<HLoadNamedField>(boilerplate, access)); | 2476 Add<HLoadNamedField>(boilerplate, access)); |
| 2475 } | 2477 } |
| 2476 } | 2478 } |
| 2477 | 2479 |
| 2478 // Create an allocation site info if requested. | 2480 // Create an allocation site info if requested. |
| 2479 if (mode == TRACK_ALLOCATION_SITE) { | 2481 if (mode == TRACK_ALLOCATION_SITE) { |
| 2480 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); | 2482 BuildCreateAllocationMemento( |
| 2483 object, Add<HConstant>(JSArray::kSize), allocation_site); |
| 2481 } | 2484 } |
| 2482 | 2485 |
| 2483 if (length > 0) { | 2486 if (length > 0) { |
| 2484 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 2487 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 2485 HValue* object_elements; | 2488 HValue* object_elements; |
| 2486 if (IsFastDoubleElementsKind(kind)) { | 2489 if (IsFastDoubleElementsKind(kind)) { |
| 2487 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); | 2490 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); |
| 2488 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), | 2491 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), |
| 2489 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); | 2492 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); |
| 2490 } else { | 2493 } else { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2563 BuildCheckMap(value, type->Classes().Current()); | 2566 BuildCheckMap(value, type->Classes().Current()); |
| 2564 } else { | 2567 } else { |
| 2565 if_nil.Deopt("Too many undetectable types"); | 2568 if_nil.Deopt("Too many undetectable types"); |
| 2566 } | 2569 } |
| 2567 } | 2570 } |
| 2568 | 2571 |
| 2569 if_nil.CaptureContinuation(continuation); | 2572 if_nil.CaptureContinuation(continuation); |
| 2570 } | 2573 } |
| 2571 | 2574 |
| 2572 | 2575 |
| 2573 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, | 2576 void HGraphBuilder::BuildCreateAllocationMemento( |
| 2574 int previous_object_size, | 2577 HValue* previous_object, |
| 2575 HValue* alloc_site) { | 2578 HValue* previous_object_size, |
| 2576 ASSERT(alloc_site != NULL); | 2579 HValue* allocation_site) { |
| 2577 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( | 2580 ASSERT(allocation_site != NULL); |
| 2581 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( |
| 2578 previous_object, previous_object_size); | 2582 previous_object, previous_object_size); |
| 2579 Handle<Map> alloc_memento_map = | 2583 AddStoreMapConstant( |
| 2580 isolate()->factory()->allocation_memento_map(); | 2584 allocation_memento, isolate()->factory()->allocation_memento_map()); |
| 2581 AddStoreMapConstant(alloc_memento, alloc_memento_map); | 2585 Add<HStoreNamedField>( |
| 2582 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); | 2586 allocation_memento, |
| 2583 Add<HStoreNamedField>(alloc_memento, access, alloc_site); | 2587 HObjectAccess::ForAllocationMementoSite(), |
| 2584 return alloc_memento; | 2588 allocation_site); |
| 2589 if (FLAG_allocation_site_pretenuring) { |
| 2590 HValue* memento_create_count = Add<HLoadNamedField>( |
| 2591 allocation_site, HObjectAccess::ForAllocationSiteOffset( |
| 2592 AllocationSite::kMementoCreateCountOffset)); |
| 2593 memento_create_count = AddUncasted<HAdd>( |
| 2594 memento_create_count, graph()->GetConstant1()); |
| 2595 // This smi value is reset to zero after every gc, overflow isn't a problem |
| 2596 // since the counter is bounded by the new space size. |
| 2597 memento_create_count->ClearFlag(HValue::kCanOverflow); |
| 2598 HStoreNamedField* store = Add<HStoreNamedField>( |
| 2599 allocation_site, HObjectAccess::ForAllocationSiteOffset( |
| 2600 AllocationSite::kMementoCreateCountOffset), memento_create_count); |
| 2601 // No write barrier needed to store a smi. |
| 2602 store->SkipWriteBarrier(); |
| 2603 } |
| 2585 } | 2604 } |
| 2586 | 2605 |
| 2587 | 2606 |
| 2588 HInstruction* HGraphBuilder::BuildGetNativeContext() { | 2607 HInstruction* HGraphBuilder::BuildGetNativeContext() { |
| 2589 // Get the global context, then the native context | 2608 // Get the global context, then the native context |
| 2590 HInstruction* global_object = Add<HGlobalObject>(); | 2609 HInstruction* global_object = Add<HGlobalObject>(); |
| 2591 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 2610 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 2592 GlobalObject::kNativeContextOffset); | 2611 GlobalObject::kNativeContextOffset); |
| 2593 return Add<HLoadNamedField>(global_object, access); | 2612 return Add<HLoadNamedField>(global_object, access); |
| 2594 } | 2613 } |
| (...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3545 | 3564 |
| 3546 void TestContext::BuildBranch(HValue* value) { | 3565 void TestContext::BuildBranch(HValue* value) { |
| 3547 // We expect the graph to be in edge-split form: there is no edge that | 3566 // We expect the graph to be in edge-split form: there is no edge that |
| 3548 // connects a branch node to a join node. We conservatively ensure that | 3567 // connects a branch node to a join node. We conservatively ensure that |
| 3549 // property by always adding an empty block on the outgoing edges of this | 3568 // property by always adding an empty block on the outgoing edges of this |
| 3550 // branch. | 3569 // branch. |
| 3551 HOptimizedGraphBuilder* builder = owner(); | 3570 HOptimizedGraphBuilder* builder = owner(); |
| 3552 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 3571 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
| 3553 builder->Bailout(kArgumentsObjectValueInATestContext); | 3572 builder->Bailout(kArgumentsObjectValueInATestContext); |
| 3554 } | 3573 } |
| 3555 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | |
| 3556 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | |
| 3557 ToBooleanStub::Types expected(condition()->to_boolean_types()); | 3574 ToBooleanStub::Types expected(condition()->to_boolean_types()); |
| 3558 builder->FinishCurrentBlock(builder->New<HBranch>( | 3575 ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None()); |
| 3559 value, expected, empty_true, empty_false)); | |
| 3560 | |
| 3561 owner()->Goto(empty_true, if_true(), builder->function_state()); | |
| 3562 owner()->Goto(empty_false , if_false(), builder->function_state()); | |
| 3563 builder->set_current_block(NULL); | |
| 3564 } | 3576 } |
| 3565 | 3577 |
| 3566 | 3578 |
| 3567 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. | 3579 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. |
| 3568 #define CHECK_BAILOUT(call) \ | 3580 #define CHECK_BAILOUT(call) \ |
| 3569 do { \ | 3581 do { \ |
| 3570 call; \ | 3582 call; \ |
| 3571 if (HasStackOverflow()) return; \ | 3583 if (HasStackOverflow()) return; \ |
| 3572 } while (false) | 3584 } while (false) |
| 3573 | 3585 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3745 Run<HRedundantPhiEliminationPhase>(); | 3757 Run<HRedundantPhiEliminationPhase>(); |
| 3746 if (!CheckArgumentsPhiUses()) { | 3758 if (!CheckArgumentsPhiUses()) { |
| 3747 *bailout_reason = kUnsupportedPhiUseOfArguments; | 3759 *bailout_reason = kUnsupportedPhiUseOfArguments; |
| 3748 return false; | 3760 return false; |
| 3749 } | 3761 } |
| 3750 | 3762 |
| 3751 // Find and mark unreachable code to simplify optimizations, especially gvn, | 3763 // Find and mark unreachable code to simplify optimizations, especially gvn, |
| 3752 // where unreachable code could unnecessarily defeat LICM. | 3764 // where unreachable code could unnecessarily defeat LICM. |
| 3753 Run<HMarkUnreachableBlocksPhase>(); | 3765 Run<HMarkUnreachableBlocksPhase>(); |
| 3754 | 3766 |
| 3755 if (FLAG_check_elimination) Run<HCheckEliminationPhase>(); | |
| 3756 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); | 3767 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
| 3757 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); | 3768 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); |
| 3758 | 3769 |
| 3759 if (FLAG_load_elimination) Run<HLoadEliminationPhase>(); | 3770 if (FLAG_load_elimination) Run<HLoadEliminationPhase>(); |
| 3760 | 3771 |
| 3761 CollectPhis(); | 3772 CollectPhis(); |
| 3762 | 3773 |
| 3763 if (has_osr()) osr()->FinishOsrValues(); | 3774 if (has_osr()) osr()->FinishOsrValues(); |
| 3764 | 3775 |
| 3765 Run<HInferRepresentationPhase>(); | 3776 Run<HInferRepresentationPhase>(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3776 | 3787 |
| 3777 // Must be performed before canonicalization to ensure that Canonicalize | 3788 // Must be performed before canonicalization to ensure that Canonicalize |
| 3778 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with | 3789 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
| 3779 // zero. | 3790 // zero. |
| 3780 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); | 3791 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); |
| 3781 | 3792 |
| 3782 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>(); | 3793 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>(); |
| 3783 | 3794 |
| 3784 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); | 3795 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
| 3785 | 3796 |
| 3797 if (FLAG_check_elimination) Run<HCheckEliminationPhase>(); |
| 3798 |
| 3786 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); | 3799 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); |
| 3787 | 3800 |
| 3788 Run<HComputeChangeUndefinedToNaN>(); | 3801 Run<HComputeChangeUndefinedToNaN>(); |
| 3789 Run<HComputeMinusZeroChecksPhase>(); | 3802 Run<HComputeMinusZeroChecksPhase>(); |
| 3790 | 3803 |
| 3791 // Eliminate redundant stack checks on backwards branches. | 3804 // Eliminate redundant stack checks on backwards branches. |
| 3792 Run<HStackCheckEliminationPhase>(); | 3805 Run<HStackCheckEliminationPhase>(); |
| 3793 | 3806 |
| 3794 if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>(); | 3807 if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>(); |
| 3795 if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>(); | 3808 if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>(); |
| (...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5099 AllocationSiteUsageContext usage_context(isolate(), site, false); | 5112 AllocationSiteUsageContext usage_context(isolate(), site, false); |
| 5100 usage_context.EnterNewScope(); | 5113 usage_context.EnterNewScope(); |
| 5101 literal = BuildFastLiteral(boilerplate_object, &usage_context); | 5114 literal = BuildFastLiteral(boilerplate_object, &usage_context); |
| 5102 usage_context.ExitScope(site, boilerplate_object); | 5115 usage_context.ExitScope(site, boilerplate_object); |
| 5103 } else { | 5116 } else { |
| 5104 NoObservableSideEffectsScope no_effects(this); | 5117 NoObservableSideEffectsScope no_effects(this); |
| 5105 // Boilerplate already exists and constant elements are never accessed, | 5118 // Boilerplate already exists and constant elements are never accessed, |
| 5106 // pass an empty fixed array to the runtime function instead. | 5119 // pass an empty fixed array to the runtime function instead. |
| 5107 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 5120 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
| 5108 int literal_index = expr->literal_index(); | 5121 int literal_index = expr->literal_index(); |
| 5122 int flags = expr->depth() == 1 |
| 5123 ? ArrayLiteral::kShallowElements |
| 5124 : ArrayLiteral::kNoFlags; |
| 5125 flags |= ArrayLiteral::kDisableMementos; |
| 5109 | 5126 |
| 5110 Add<HPushArgument>(Add<HConstant>(literals)); | 5127 Add<HPushArgument>(Add<HConstant>(literals)); |
| 5111 Add<HPushArgument>(Add<HConstant>(literal_index)); | 5128 Add<HPushArgument>(Add<HConstant>(literal_index)); |
| 5112 Add<HPushArgument>(Add<HConstant>(constants)); | 5129 Add<HPushArgument>(Add<HConstant>(constants)); |
| 5130 Add<HPushArgument>(Add<HConstant>(flags)); |
| 5113 | 5131 |
| 5114 // TODO(mvstanton): Consider a flag to turn off creation of any | 5132 // TODO(mvstanton): Consider a flag to turn off creation of any |
| 5115 // AllocationMementos for this call: we are in crankshaft and should have | 5133 // AllocationMementos for this call: we are in crankshaft and should have |
| 5116 // learned enough about transition behavior to stop emitting mementos. | 5134 // learned enough about transition behavior to stop emitting mementos. |
| 5117 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; | 5135 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; |
| 5118 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 5136 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 5119 Runtime::FunctionForId(function_id), | 5137 Runtime::FunctionForId(function_id), |
| 5120 3); | 5138 4); |
| 5121 | 5139 |
| 5122 // De-opt if elements kind changed from boilerplate_elements_kind. | 5140 // De-opt if elements kind changed from boilerplate_elements_kind. |
| 5123 Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate()); | 5141 Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate()); |
| 5124 literal = Add<HCheckMaps>(literal, map, top_info()); | 5142 literal = Add<HCheckMaps>(literal, map, top_info()); |
| 5125 } | 5143 } |
| 5126 | 5144 |
| 5127 // The array is expected in the bailout environment during computation | 5145 // The array is expected in the bailout environment during computation |
| 5128 // of the property values and is the value of the entire expression. | 5146 // of the property values and is the value of the entire expression. |
| 5129 Push(literal); | 5147 Push(literal); |
| 5130 // The literal index is on the stack, too. | 5148 // The literal index is on the stack, too. |
| (...skipping 1626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6757 if (!expr->ComputeTarget(info.map(), name)) return false; | 6775 if (!expr->ComputeTarget(info.map(), name)) return false; |
| 6758 | 6776 |
| 6759 BuildCheckHeapObject(receiver); | 6777 BuildCheckHeapObject(receiver); |
| 6760 Add<HCheckMaps>(receiver, types); | 6778 Add<HCheckMaps>(receiver, types); |
| 6761 AddCheckPrototypeMaps(expr->holder(), info.map()); | 6779 AddCheckPrototypeMaps(expr->holder(), info.map()); |
| 6762 if (FLAG_trace_inlining) { | 6780 if (FLAG_trace_inlining) { |
| 6763 Handle<JSFunction> caller = current_info()->closure(); | 6781 Handle<JSFunction> caller = current_info()->closure(); |
| 6764 SmartArrayPointer<char> caller_name = | 6782 SmartArrayPointer<char> caller_name = |
| 6765 caller->shared()->DebugName()->ToCString(); | 6783 caller->shared()->DebugName()->ToCString(); |
| 6766 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6784 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 6767 *name->ToCString(), *caller_name); | 6785 name->ToCString().get(), caller_name.get()); |
| 6768 } | 6786 } |
| 6769 | 6787 |
| 6770 if (!TryInlineCall(expr)) { | 6788 if (!TryInlineCall(expr)) { |
| 6771 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6789 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6772 HCallConstantFunction* call = | 6790 HCallConstantFunction* call = |
| 6773 New<HCallConstantFunction>(expr->target(), argument_count); | 6791 New<HCallConstantFunction>(expr->target(), argument_count); |
| 6774 PreProcessCall(call); | 6792 PreProcessCall(call); |
| 6775 AddInstruction(call); | 6793 AddInstruction(call); |
| 6776 if (!ast_context()->IsEffect()) Push(call); | 6794 if (!ast_context()->IsEffect()) Push(call); |
| 6777 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 6795 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6870 } | 6888 } |
| 6871 set_current_block(if_true); | 6889 set_current_block(if_true); |
| 6872 | 6890 |
| 6873 expr->ComputeTarget(map, name); | 6891 expr->ComputeTarget(map, name); |
| 6874 AddCheckPrototypeMaps(expr->holder(), map); | 6892 AddCheckPrototypeMaps(expr->holder(), map); |
| 6875 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 6893 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 6876 Handle<JSFunction> caller = current_info()->closure(); | 6894 Handle<JSFunction> caller = current_info()->closure(); |
| 6877 SmartArrayPointer<char> caller_name = | 6895 SmartArrayPointer<char> caller_name = |
| 6878 caller->shared()->DebugName()->ToCString(); | 6896 caller->shared()->DebugName()->ToCString(); |
| 6879 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6897 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 6880 *name->ToCString(), | 6898 name->ToCString().get(), |
| 6881 *caller_name); | 6899 caller_name.get()); |
| 6882 } | 6900 } |
| 6883 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 6901 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
| 6884 // Trying to inline will signal that we should bailout from the | 6902 // Trying to inline will signal that we should bailout from the |
| 6885 // entire compilation by setting stack overflow on the visitor. | 6903 // entire compilation by setting stack overflow on the visitor. |
| 6886 if (HasStackOverflow()) return; | 6904 if (HasStackOverflow()) return; |
| 6887 } else { | 6905 } else { |
| 6888 HCallConstantFunction* call = | 6906 HCallConstantFunction* call = |
| 6889 New<HCallConstantFunction>(expr->target(), argument_count); | 6907 New<HCallConstantFunction>(expr->target(), argument_count); |
| 6890 PreProcessCall(call); | 6908 PreProcessCall(call); |
| 6891 AddInstruction(call); | 6909 AddInstruction(call); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6935 | 6953 |
| 6936 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, | 6954 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, |
| 6937 Handle<JSFunction> caller, | 6955 Handle<JSFunction> caller, |
| 6938 const char* reason) { | 6956 const char* reason) { |
| 6939 if (FLAG_trace_inlining) { | 6957 if (FLAG_trace_inlining) { |
| 6940 SmartArrayPointer<char> target_name = | 6958 SmartArrayPointer<char> target_name = |
| 6941 target->shared()->DebugName()->ToCString(); | 6959 target->shared()->DebugName()->ToCString(); |
| 6942 SmartArrayPointer<char> caller_name = | 6960 SmartArrayPointer<char> caller_name = |
| 6943 caller->shared()->DebugName()->ToCString(); | 6961 caller->shared()->DebugName()->ToCString(); |
| 6944 if (reason == NULL) { | 6962 if (reason == NULL) { |
| 6945 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); | 6963 PrintF("Inlined %s called from %s.\n", target_name.get(), |
| 6964 caller_name.get()); |
| 6946 } else { | 6965 } else { |
| 6947 PrintF("Did not inline %s called from %s (%s).\n", | 6966 PrintF("Did not inline %s called from %s (%s).\n", |
| 6948 *target_name, *caller_name, reason); | 6967 target_name.get(), caller_name.get(), reason); |
| 6949 } | 6968 } |
| 6950 } | 6969 } |
| 6951 } | 6970 } |
| 6952 | 6971 |
| 6953 | 6972 |
| 6954 static const int kNotInlinable = 1000000000; | 6973 static const int kNotInlinable = 1000000000; |
| 6955 | 6974 |
| 6956 | 6975 |
| 6957 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { | 6976 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { |
| 6958 if (!FLAG_use_inlining) return kNotInlinable; | 6977 if (!FLAG_use_inlining) return kNotInlinable; |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7529 if (args->length() != 2) return false; | 7548 if (args->length() != 2) return false; |
| 7530 | 7549 |
| 7531 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 7550 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 7532 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 7551 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 7533 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); | 7552 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 7534 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 7553 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 7535 | 7554 |
| 7536 // Found pattern f.apply(receiver, arguments). | 7555 // Found pattern f.apply(receiver, arguments). |
| 7537 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true); | 7556 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true); |
| 7538 HValue* function = Top(); | 7557 HValue* function = Top(); |
| 7558 |
| 7539 AddCheckConstantFunction(expr->holder(), function, function_map); | 7559 AddCheckConstantFunction(expr->holder(), function, function_map); |
| 7540 Drop(1); | 7560 Drop(1); |
| 7541 | 7561 |
| 7542 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); | 7562 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); |
| 7543 HValue* receiver = Pop(); | 7563 HValue* receiver = Pop(); |
| 7544 | 7564 |
| 7545 if (function_state()->outer() == NULL) { | 7565 if (function_state()->outer() == NULL) { |
| 7546 HInstruction* elements = Add<HArgumentsElements>(false); | 7566 HInstruction* elements = Add<HArgumentsElements>(false); |
| 7547 HInstruction* length = Add<HArgumentsLength>(elements); | 7567 HInstruction* length = Add<HArgumentsLength>(elements); |
| 7548 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); | 7568 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 7559 function_state()->entry()->arguments_object()->arguments_count()); | 7579 function_state()->entry()->arguments_object()->arguments_count()); |
| 7560 HArgumentsObject* args = function_state()->entry()->arguments_object(); | 7580 HArgumentsObject* args = function_state()->entry()->arguments_object(); |
| 7561 const ZoneList<HValue*>* arguments_values = args->arguments_values(); | 7581 const ZoneList<HValue*>* arguments_values = args->arguments_values(); |
| 7562 int arguments_count = arguments_values->length(); | 7582 int arguments_count = arguments_values->length(); |
| 7563 Push(BuildWrapReceiver(receiver, function)); | 7583 Push(BuildWrapReceiver(receiver, function)); |
| 7564 for (int i = 1; i < arguments_count; i++) { | 7584 for (int i = 1; i < arguments_count; i++) { |
| 7565 Push(arguments_values->at(i)); | 7585 Push(arguments_values->at(i)); |
| 7566 } | 7586 } |
| 7567 | 7587 |
| 7568 Handle<JSFunction> known_function; | 7588 Handle<JSFunction> known_function; |
| 7569 if (function->IsConstant()) { | 7589 if (function->IsConstant() && |
| 7570 HConstant* constant_function = HConstant::cast(function); | 7590 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
| 7571 known_function = Handle<JSFunction>::cast( | 7591 known_function = Handle<JSFunction>::cast( |
| 7572 constant_function->handle(isolate())); | 7592 HConstant::cast(function)->handle(isolate())); |
| 7573 int args_count = arguments_count - 1; // Excluding receiver. | 7593 int args_count = arguments_count - 1; // Excluding receiver. |
| 7574 if (TryInlineApply(known_function, expr, args_count)) return true; | 7594 if (TryInlineApply(known_function, expr, args_count)) return true; |
| 7575 } | 7595 } |
| 7576 | 7596 |
| 7577 Drop(arguments_count - 1); | 7597 Drop(arguments_count - 1); |
| 7578 Push(Add<HPushArgument>(Pop())); | 7598 Push(Add<HPushArgument>(Pop())); |
| 7579 for (int i = 1; i < arguments_count; i++) { | 7599 for (int i = 1; i < arguments_count; i++) { |
| 7580 Push(Add<HPushArgument>(arguments_values->at(i))); | 7600 Push(Add<HPushArgument>(arguments_values->at(i))); |
| 7581 } | 7601 } |
| 7582 | 7602 |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8047 &HOptimizedGraphBuilder::Generate##Name, | 8067 &HOptimizedGraphBuilder::Generate##Name, |
| 8048 | 8068 |
| 8049 const HOptimizedGraphBuilder::InlineFunctionGenerator | 8069 const HOptimizedGraphBuilder::InlineFunctionGenerator |
| 8050 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { | 8070 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { |
| 8051 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 8071 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 8052 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 8072 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 8053 }; | 8073 }; |
| 8054 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 8074 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
| 8055 | 8075 |
| 8056 | 8076 |
| 8077 template <class ViewClass> |
| 8078 void HGraphBuilder::BuildArrayBufferViewInitialization( |
| 8079 HValue* obj, |
| 8080 HValue* buffer, |
| 8081 HValue* byte_offset, |
| 8082 HValue* byte_length) { |
| 8083 |
| 8084 for (int offset = ViewClass::kSize; |
| 8085 offset < ViewClass::kSizeWithInternalFields; |
| 8086 offset += kPointerSize) { |
| 8087 Add<HStoreNamedField>(obj, |
| 8088 HObjectAccess::ForJSObjectOffset(offset), |
| 8089 Add<HConstant>(static_cast<int32_t>(0))); |
| 8090 } |
| 8091 |
| 8092 Add<HStoreNamedField>( |
| 8093 obj, |
| 8094 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); |
| 8095 Add<HStoreNamedField>( |
| 8096 obj, |
| 8097 HObjectAccess::ForJSArrayBufferViewByteOffset(), |
| 8098 byte_offset); |
| 8099 Add<HStoreNamedField>( |
| 8100 obj, |
| 8101 HObjectAccess::ForJSArrayBufferViewByteLength(), |
| 8102 byte_length); |
| 8103 |
| 8104 HObjectAccess weak_first_view_access = |
| 8105 HObjectAccess::ForJSArrayBufferWeakFirstView(); |
| 8106 Add<HStoreNamedField>(obj, |
| 8107 HObjectAccess::ForJSArrayBufferViewWeakNext(), |
| 8108 Add<HLoadNamedField>(buffer, weak_first_view_access)); |
| 8109 Add<HStoreNamedField>(buffer, weak_first_view_access, obj); |
| 8110 } |
| 8111 |
| 8112 |
| 8057 void HOptimizedGraphBuilder::VisitDataViewInitialize( | 8113 void HOptimizedGraphBuilder::VisitDataViewInitialize( |
| 8058 CallRuntime* expr) { | 8114 CallRuntime* expr) { |
| 8059 ZoneList<Expression*>* arguments = expr->arguments(); | 8115 ZoneList<Expression*>* arguments = expr->arguments(); |
| 8060 | 8116 |
| 8061 NoObservableSideEffectsScope scope(this); | 8117 NoObservableSideEffectsScope scope(this); |
| 8062 ASSERT(arguments->length()== 4); | 8118 ASSERT(arguments->length()== 4); |
| 8063 CHECK_ALIVE(VisitForValue(arguments->at(0))); | 8119 CHECK_ALIVE(VisitForValue(arguments->at(0))); |
| 8064 HValue* obj = Pop(); | 8120 HValue* obj = Pop(); |
| 8065 | 8121 |
| 8066 CHECK_ALIVE(VisitForValue(arguments->at(1))); | 8122 CHECK_ALIVE(VisitForValue(arguments->at(1))); |
| 8067 HValue* buffer = Pop(); | 8123 HValue* buffer = Pop(); |
| 8068 | 8124 |
| 8069 CHECK_ALIVE(VisitForValue(arguments->at(2))); | 8125 CHECK_ALIVE(VisitForValue(arguments->at(2))); |
| 8070 HValue* byte_offset = Pop(); | 8126 HValue* byte_offset = Pop(); |
| 8071 | 8127 |
| 8072 CHECK_ALIVE(VisitForValue(arguments->at(3))); | 8128 CHECK_ALIVE(VisitForValue(arguments->at(3))); |
| 8073 HValue* byte_length = Pop(); | 8129 HValue* byte_length = Pop(); |
| 8074 | 8130 |
| 8075 for (int offset = JSDataView::kSize; | 8131 BuildArrayBufferViewInitialization<JSDataView>( |
| 8076 offset < JSDataView::kSizeWithInternalFields; | 8132 obj, buffer, byte_offset, byte_length); |
| 8077 offset += kPointerSize) { | |
| 8078 Add<HStoreNamedField>(obj, | |
| 8079 HObjectAccess::ForJSObjectOffset(offset), | |
| 8080 Add<HConstant>(static_cast<int32_t>(0))); | |
| 8081 } | |
| 8082 | |
| 8083 Add<HStoreNamedField>(obj, | |
| 8084 HObjectAccess::ForJSObjectOffset(JSDataView::kBufferOffset), buffer); | |
| 8085 Add<HStoreNamedField>(obj, | |
| 8086 HObjectAccess::ForJSObjectOffset(JSDataView::kByteOffsetOffset), | |
| 8087 byte_offset); | |
| 8088 Add<HStoreNamedField>(obj, | |
| 8089 HObjectAccess::ForJSObjectOffset(JSDataView::kByteLengthOffset), | |
| 8090 byte_length); | |
| 8091 | |
| 8092 Add<HStoreNamedField>(obj, | |
| 8093 HObjectAccess::ForJSObjectOffset(JSDataView::kWeakNextOffset), | |
| 8094 Add<HLoadNamedField>(buffer, | |
| 8095 HObjectAccess::ForJSObjectOffset( | |
| 8096 JSArrayBuffer::kWeakFirstViewOffset))); | |
| 8097 Add<HStoreNamedField>(buffer, | |
| 8098 HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset), | |
| 8099 obj); | |
| 8100 } | 8133 } |
| 8101 | 8134 |
| 8102 | 8135 |
| 8136 void HOptimizedGraphBuilder::VisitTypedArrayInitialize( |
| 8137 CallRuntime* expr) { |
| 8138 ZoneList<Expression*>* arguments = expr->arguments(); |
| 8139 |
| 8140 NoObservableSideEffectsScope scope(this); |
| 8141 static const int kObjectArg = 0; |
| 8142 static const int kArrayIdArg = 1; |
| 8143 static const int kBufferArg = 2; |
| 8144 static const int kByteOffsetArg = 3; |
| 8145 static const int kByteLengthArg = 4; |
| 8146 static const int kArgsLength = 5; |
| 8147 ASSERT(arguments->length() == kArgsLength); |
| 8148 |
| 8149 |
| 8150 CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg))); |
| 8151 HValue* obj = Pop(); |
| 8152 |
| 8153 ASSERT(arguments->at(kArrayIdArg)->node_type() == AstNode::kLiteral); |
| 8154 Handle<Object> value = |
| 8155 static_cast<Literal*>(arguments->at(kArrayIdArg))->value(); |
| 8156 ASSERT(value->IsSmi()); |
| 8157 int array_id = Smi::cast(*value)->value(); |
| 8158 |
| 8159 CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg))); |
| 8160 HValue* buffer = Pop(); |
| 8161 |
| 8162 HValue* byte_offset; |
| 8163 bool is_zero_byte_offset; |
| 8164 |
| 8165 if (arguments->at(kByteOffsetArg)->node_type() == AstNode::kLiteral |
| 8166 && Smi::FromInt(0) == |
| 8167 *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) { |
| 8168 byte_offset = Add<HConstant>(static_cast<int32_t>(0)); |
| 8169 is_zero_byte_offset = true; |
| 8170 } else { |
| 8171 CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg))); |
| 8172 byte_offset = Pop(); |
| 8173 is_zero_byte_offset = false; |
| 8174 } |
| 8175 |
| 8176 CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg))); |
| 8177 HValue* byte_length = Pop(); |
| 8178 |
| 8179 IfBuilder byte_offset_smi(this); |
| 8180 |
| 8181 if (!is_zero_byte_offset) { |
| 8182 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset); |
| 8183 byte_offset_smi.Then(); |
| 8184 } |
| 8185 |
| 8186 { // byte_offset is Smi. |
| 8187 BuildArrayBufferViewInitialization<JSTypedArray>( |
| 8188 obj, buffer, byte_offset, byte_length); |
| 8189 |
| 8190 ExternalArrayType array_type = kExternalByteArray; // Bogus initialization. |
| 8191 size_t element_size = 1; // Bogus initialization. |
| 8192 Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size); |
| 8193 |
| 8194 HInstruction* length = AddUncasted<HDiv>(byte_length, |
| 8195 Add<HConstant>(static_cast<int32_t>(element_size))); |
| 8196 |
| 8197 Add<HStoreNamedField>(obj, |
| 8198 HObjectAccess::ForJSTypedArrayLength(), |
| 8199 length); |
| 8200 |
| 8201 HValue* elements = |
| 8202 Add<HAllocate>( |
| 8203 Add<HConstant>(ExternalArray::kAlignedSize), |
| 8204 HType::JSArray(), |
| 8205 NOT_TENURED, |
| 8206 static_cast<InstanceType>(FIRST_EXTERNAL_ARRAY_TYPE + array_type)); |
| 8207 |
| 8208 Handle<Map> external_array_map( |
| 8209 isolate()->heap()->MapForExternalArrayType(array_type)); |
| 8210 Add<HStoreNamedField>(elements, |
| 8211 HObjectAccess::ForMap(), |
| 8212 Add<HConstant>(external_array_map)); |
| 8213 |
| 8214 HValue* backing_store = Add<HLoadNamedField>( |
| 8215 buffer, HObjectAccess::ForJSArrayBufferBackingStore()); |
| 8216 |
| 8217 HValue* typed_array_start; |
| 8218 if (is_zero_byte_offset) { |
| 8219 typed_array_start = backing_store; |
| 8220 } else { |
| 8221 HInstruction* external_pointer = |
| 8222 AddUncasted<HAdd>(backing_store, byte_offset); |
| 8223 // Arguments are checked prior to call to TypedArrayInitialize, |
| 8224 // including byte_offset. |
| 8225 external_pointer->ClearFlag(HValue::kCanOverflow); |
| 8226 typed_array_start = external_pointer; |
| 8227 } |
| 8228 |
| 8229 Add<HStoreNamedField>(elements, |
| 8230 HObjectAccess::ForExternalArrayExternalPointer(), |
| 8231 typed_array_start); |
| 8232 Add<HStoreNamedField>(elements, |
| 8233 HObjectAccess::ForFixedArrayLength(), |
| 8234 length); |
| 8235 Add<HStoreNamedField>( |
| 8236 obj, HObjectAccess::ForElementsPointer(), elements); |
| 8237 } |
| 8238 |
| 8239 if (!is_zero_byte_offset) { |
| 8240 byte_offset_smi.Else(); |
| 8241 { // byte_offset is not Smi. |
| 8242 Push(Add<HPushArgument>(obj)); |
| 8243 VisitArgument(arguments->at(kArrayIdArg)); |
| 8244 Push(Add<HPushArgument>(buffer)); |
| 8245 Push(Add<HPushArgument>(byte_offset)); |
| 8246 Push(Add<HPushArgument>(byte_length)); |
| 8247 Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength); |
| 8248 Drop(kArgsLength); |
| 8249 } |
| 8250 } |
| 8251 byte_offset_smi.End(); |
| 8252 } |
| 8253 |
| 8254 |
| 8103 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 8255 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 8104 ASSERT(!HasStackOverflow()); | 8256 ASSERT(!HasStackOverflow()); |
| 8105 ASSERT(current_block() != NULL); | 8257 ASSERT(current_block() != NULL); |
| 8106 ASSERT(current_block()->HasPredecessor()); | 8258 ASSERT(current_block()->HasPredecessor()); |
| 8107 if (expr->is_jsruntime()) { | 8259 if (expr->is_jsruntime()) { |
| 8108 return Bailout(kCallToAJavaScriptRuntimeFunction); | 8260 return Bailout(kCallToAJavaScriptRuntimeFunction); |
| 8109 } | 8261 } |
| 8110 | 8262 |
| 8111 const Runtime::Function* function = expr->function(); | 8263 const Runtime::Function* function = expr->function(); |
| 8112 ASSERT(function != NULL); | 8264 ASSERT(function != NULL); |
| 8113 | 8265 |
| 8114 if (function->function_id == Runtime::kDataViewInitialize) { | 8266 if (function->function_id == Runtime::kDataViewInitialize) { |
| 8115 return VisitDataViewInitialize(expr); | 8267 return VisitDataViewInitialize(expr); |
| 8116 } | 8268 } |
| 8117 | 8269 |
| 8270 if (function->function_id == Runtime::kTypedArrayInitialize) { |
| 8271 return VisitTypedArrayInitialize(expr); |
| 8272 } |
| 8273 |
| 8274 if (function->function_id == Runtime::kMaxSmi) { |
| 8275 ASSERT(expr->arguments()->length() == 0); |
| 8276 HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue)); |
| 8277 return ast_context()->ReturnInstruction(max_smi, expr->id()); |
| 8278 } |
| 8279 |
| 8118 if (function->intrinsic_type == Runtime::INLINE) { | 8280 if (function->intrinsic_type == Runtime::INLINE) { |
| 8119 ASSERT(expr->name()->length() > 0); | 8281 ASSERT(expr->name()->length() > 0); |
| 8120 ASSERT(expr->name()->Get(0) == '_'); | 8282 ASSERT(expr->name()->Get(0) == '_'); |
| 8121 // Call to an inline function. | 8283 // Call to an inline function. |
| 8122 int lookup_index = static_cast<int>(function->function_id) - | 8284 int lookup_index = static_cast<int>(function->function_id) - |
| 8123 static_cast<int>(Runtime::kFirstInlineFunction); | 8285 static_cast<int>(Runtime::kFirstInlineFunction); |
| 8124 ASSERT(lookup_index >= 0); | 8286 ASSERT(lookup_index >= 0); |
| 8125 ASSERT(static_cast<size_t>(lookup_index) < | 8287 ASSERT(static_cast<size_t>(lookup_index) < |
| 8126 ARRAY_SIZE(kInlineFunctionGenerators)); | 8288 ARRAY_SIZE(kInlineFunctionGenerators)); |
| 8127 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 8289 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
| (...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8693 break; | 8855 break; |
| 8694 case Token::SUB: | 8856 case Token::SUB: |
| 8695 instr = AddUncasted<HSub>(left, right); | 8857 instr = AddUncasted<HSub>(left, right); |
| 8696 break; | 8858 break; |
| 8697 case Token::MUL: | 8859 case Token::MUL: |
| 8698 instr = AddUncasted<HMul>(left, right); | 8860 instr = AddUncasted<HMul>(left, right); |
| 8699 break; | 8861 break; |
| 8700 case Token::MOD: { | 8862 case Token::MOD: { |
| 8701 if (fixed_right_arg.has_value) { | 8863 if (fixed_right_arg.has_value) { |
| 8702 if (right->IsConstant()) { | 8864 if (right->IsConstant()) { |
| 8703 ASSERT_EQ(fixed_right_arg.value, | 8865 HConstant* c_right = HConstant::cast(right); |
| 8704 HConstant::cast(right)->Integer32Value()); | 8866 if (c_right->HasInteger32Value()) { |
| 8867 ASSERT_EQ(fixed_right_arg.value, c_right->Integer32Value()); |
| 8868 } |
| 8705 } else { | 8869 } else { |
| 8706 HConstant* fixed_right = Add<HConstant>( | 8870 HConstant* fixed_right = Add<HConstant>( |
| 8707 static_cast<int>(fixed_right_arg.value)); | 8871 static_cast<int>(fixed_right_arg.value)); |
| 8708 IfBuilder if_same(this); | 8872 IfBuilder if_same(this); |
| 8709 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); | 8873 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); |
| 8710 if_same.Then(); | 8874 if_same.Then(); |
| 8711 if_same.ElseDeopt("Unexpected RHS of binary operation"); | 8875 if_same.ElseDeopt("Unexpected RHS of binary operation"); |
| 8712 right = fixed_right; | 8876 right = fixed_right; |
| 8713 } | 8877 } |
| 8714 } | 8878 } |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9167 return New<HConstant>( | 9331 return New<HConstant>( |
| 9168 function_state()->compilation_info()->closure()); | 9332 function_state()->compilation_info()->closure()); |
| 9169 } else { | 9333 } else { |
| 9170 return New<HThisFunction>(); | 9334 return New<HThisFunction>(); |
| 9171 } | 9335 } |
| 9172 } | 9336 } |
| 9173 | 9337 |
| 9174 | 9338 |
| 9175 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 9339 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| 9176 Handle<JSObject> boilerplate_object, | 9340 Handle<JSObject> boilerplate_object, |
| 9177 AllocationSiteContext* site_context) { | 9341 AllocationSiteUsageContext* site_context) { |
| 9178 NoObservableSideEffectsScope no_effects(this); | 9342 NoObservableSideEffectsScope no_effects(this); |
| 9179 InstanceType instance_type = boilerplate_object->map()->instance_type(); | 9343 InstanceType instance_type = boilerplate_object->map()->instance_type(); |
| 9180 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); | 9344 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); |
| 9181 | 9345 |
| 9182 HType type = instance_type == JS_ARRAY_TYPE | 9346 HType type = instance_type == JS_ARRAY_TYPE |
| 9183 ? HType::JSArray() : HType::JSObject(); | 9347 ? HType::JSArray() : HType::JSObject(); |
| 9184 HValue* object_size_constant = Add<HConstant>( | 9348 HValue* object_size_constant = Add<HConstant>( |
| 9185 boilerplate_object->map()->instance_size()); | 9349 boilerplate_object->map()->instance_size()); |
| 9350 |
| 9351 // We should pull pre-tenure mode from the allocation site. |
| 9352 // For now, just see what it says, and remark on it if it sez |
| 9353 // we should pretenure. That means the rudimentary counting in the garbage |
| 9354 // collector is having an effect. |
| 9355 PretenureFlag pretenure_flag = isolate()->heap()->GetPretenureMode(); |
| 9356 if (FLAG_allocation_site_pretenuring) { |
| 9357 pretenure_flag = site_context->current()->GetPretenureMode() |
| 9358 ? TENURED |
| 9359 : NOT_TENURED; |
| 9360 } |
| 9361 |
| 9186 HInstruction* object = Add<HAllocate>(object_size_constant, type, | 9362 HInstruction* object = Add<HAllocate>(object_size_constant, type, |
| 9187 isolate()->heap()->GetPretenureMode(), instance_type); | 9363 pretenure_flag, instance_type, site_context->current()); |
| 9188 | 9364 |
| 9189 BuildEmitObjectHeader(boilerplate_object, object); | 9365 BuildEmitObjectHeader(boilerplate_object, object); |
| 9190 | 9366 |
| 9191 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 9367 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 9192 int elements_size = (elements->length() > 0 && | 9368 int elements_size = (elements->length() > 0 && |
| 9193 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 9369 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
| 9194 elements->Size() : 0; | 9370 elements->Size() : 0; |
| 9195 | 9371 |
| 9196 HInstruction* object_elements = NULL; | 9372 HInstruction* object_elements = NULL; |
| 9197 if (elements_size > 0) { | 9373 if (elements_size > 0) { |
| 9198 HValue* object_elements_size = Add<HConstant>(elements_size); | 9374 HValue* object_elements_size = Add<HConstant>(elements_size); |
| 9199 if (boilerplate_object->HasFastDoubleElements()) { | 9375 if (boilerplate_object->HasFastDoubleElements()) { |
| 9200 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), | 9376 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), |
| 9201 isolate()->heap()->GetPretenureMode(), FIXED_DOUBLE_ARRAY_TYPE); | 9377 pretenure_flag, FIXED_DOUBLE_ARRAY_TYPE, site_context->current()); |
| 9202 } else { | 9378 } else { |
| 9203 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), | 9379 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), |
| 9204 isolate()->heap()->GetPretenureMode(), FIXED_ARRAY_TYPE); | 9380 pretenure_flag, FIXED_ARRAY_TYPE, site_context->current()); |
| 9205 } | 9381 } |
| 9206 } | 9382 } |
| 9207 BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements); | 9383 BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements); |
| 9208 | 9384 |
| 9209 // Copy object elements if non-COW. | 9385 // Copy object elements if non-COW. |
| 9210 if (object_elements != NULL) { | 9386 if (object_elements != NULL) { |
| 9211 BuildEmitElements(boilerplate_object, elements, object_elements, | 9387 BuildEmitElements(boilerplate_object, elements, object_elements, |
| 9212 site_context); | 9388 site_context); |
| 9213 } | 9389 } |
| 9214 | 9390 |
| 9215 // Copy in-object properties. | 9391 // Copy in-object properties. |
| 9216 if (boilerplate_object->map()->NumberOfFields() != 0) { | 9392 if (boilerplate_object->map()->NumberOfFields() != 0) { |
| 9217 BuildEmitInObjectProperties(boilerplate_object, object, site_context); | 9393 BuildEmitInObjectProperties(boilerplate_object, object, site_context, |
| 9394 pretenure_flag); |
| 9218 } | 9395 } |
| 9219 return object; | 9396 return object; |
| 9220 } | 9397 } |
| 9221 | 9398 |
| 9222 | 9399 |
| 9223 void HOptimizedGraphBuilder::BuildEmitObjectHeader( | 9400 void HOptimizedGraphBuilder::BuildEmitObjectHeader( |
| 9224 Handle<JSObject> boilerplate_object, | 9401 Handle<JSObject> boilerplate_object, |
| 9225 HInstruction* object) { | 9402 HInstruction* object) { |
| 9226 ASSERT(boilerplate_object->properties()->length() == 0); | 9403 ASSERT(boilerplate_object->properties()->length() == 0); |
| 9227 | 9404 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9260 object_elements = Add<HConstant>(elements_field); | 9437 object_elements = Add<HConstant>(elements_field); |
| 9261 } | 9438 } |
| 9262 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 9439 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 9263 object_elements); | 9440 object_elements); |
| 9264 } | 9441 } |
| 9265 | 9442 |
| 9266 | 9443 |
| 9267 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 9444 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| 9268 Handle<JSObject> boilerplate_object, | 9445 Handle<JSObject> boilerplate_object, |
| 9269 HInstruction* object, | 9446 HInstruction* object, |
| 9270 AllocationSiteContext* site_context) { | 9447 AllocationSiteUsageContext* site_context, |
| 9448 PretenureFlag pretenure_flag) { |
| 9271 Handle<DescriptorArray> descriptors( | 9449 Handle<DescriptorArray> descriptors( |
| 9272 boilerplate_object->map()->instance_descriptors()); | 9450 boilerplate_object->map()->instance_descriptors()); |
| 9273 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); | 9451 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); |
| 9274 | 9452 |
| 9275 int copied_fields = 0; | 9453 int copied_fields = 0; |
| 9276 for (int i = 0; i < limit; i++) { | 9454 for (int i = 0; i < limit; i++) { |
| 9277 PropertyDetails details = descriptors->GetDetails(i); | 9455 PropertyDetails details = descriptors->GetDetails(i); |
| 9278 if (details.type() != FIELD) continue; | 9456 if (details.type() != FIELD) continue; |
| 9279 copied_fields++; | 9457 copied_fields++; |
| 9280 int index = descriptors->GetFieldIndex(i); | 9458 int index = descriptors->GetFieldIndex(i); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 9296 BuildFastLiteral(value_object, site_context); | 9474 BuildFastLiteral(value_object, site_context); |
| 9297 site_context->ExitScope(current_site, value_object); | 9475 site_context->ExitScope(current_site, value_object); |
| 9298 Add<HStoreNamedField>(object, access, result); | 9476 Add<HStoreNamedField>(object, access, result); |
| 9299 } else { | 9477 } else { |
| 9300 Representation representation = details.representation(); | 9478 Representation representation = details.representation(); |
| 9301 HInstruction* value_instruction = Add<HConstant>(value); | 9479 HInstruction* value_instruction = Add<HConstant>(value); |
| 9302 | 9480 |
| 9303 if (representation.IsDouble()) { | 9481 if (representation.IsDouble()) { |
| 9304 // Allocate a HeapNumber box and store the value into it. | 9482 // Allocate a HeapNumber box and store the value into it. |
| 9305 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); | 9483 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); |
| 9306 // TODO(mvstanton): This heap number alloc does not have a corresponding | 9484 // This heap number alloc does not have a corresponding |
| 9307 // AllocationSite. That is okay because | 9485 // AllocationSite. That is okay because |
| 9308 // 1) it's a child object of another object with a valid allocation site | 9486 // 1) it's a child object of another object with a valid allocation site |
| 9309 // 2) we can just use the mode of the parent object for pretenuring | 9487 // 2) we can just use the mode of the parent object for pretenuring |
| 9310 // The todo is replace GetPretenureMode() with | |
| 9311 // site_context->top()->GetPretenureMode(). | |
| 9312 HInstruction* double_box = | 9488 HInstruction* double_box = |
| 9313 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), | 9489 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), |
| 9314 isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE); | 9490 pretenure_flag, HEAP_NUMBER_TYPE); |
| 9315 AddStoreMapConstant(double_box, | 9491 AddStoreMapConstant(double_box, |
| 9316 isolate()->factory()->heap_number_map()); | 9492 isolate()->factory()->heap_number_map()); |
| 9317 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), | 9493 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), |
| 9318 value_instruction); | 9494 value_instruction); |
| 9319 value_instruction = double_box; | 9495 value_instruction = double_box; |
| 9320 } | 9496 } |
| 9321 | 9497 |
| 9322 Add<HStoreNamedField>(object, access, value_instruction); | 9498 Add<HStoreNamedField>(object, access, value_instruction); |
| 9323 } | 9499 } |
| 9324 } | 9500 } |
| 9325 | 9501 |
| 9326 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 9502 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
| 9327 HInstruction* value_instruction = | 9503 HInstruction* value_instruction = |
| 9328 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 9504 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
| 9329 for (int i = copied_fields; i < inobject_properties; i++) { | 9505 for (int i = copied_fields; i < inobject_properties; i++) { |
| 9330 ASSERT(boilerplate_object->IsJSObject()); | 9506 ASSERT(boilerplate_object->IsJSObject()); |
| 9331 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 9507 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
| 9332 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 9508 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
| 9333 Add<HStoreNamedField>(object, access, value_instruction); | 9509 Add<HStoreNamedField>(object, access, value_instruction); |
| 9334 } | 9510 } |
| 9335 } | 9511 } |
| 9336 | 9512 |
| 9337 | 9513 |
| 9338 void HOptimizedGraphBuilder::BuildEmitElements( | 9514 void HOptimizedGraphBuilder::BuildEmitElements( |
| 9339 Handle<JSObject> boilerplate_object, | 9515 Handle<JSObject> boilerplate_object, |
| 9340 Handle<FixedArrayBase> elements, | 9516 Handle<FixedArrayBase> elements, |
| 9341 HValue* object_elements, | 9517 HValue* object_elements, |
| 9342 AllocationSiteContext* site_context) { | 9518 AllocationSiteUsageContext* site_context) { |
| 9343 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 9519 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
| 9344 int elements_length = elements->length(); | 9520 int elements_length = elements->length(); |
| 9345 HValue* object_elements_length = Add<HConstant>(elements_length); | 9521 HValue* object_elements_length = Add<HConstant>(elements_length); |
| 9346 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); | 9522 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); |
| 9347 | 9523 |
| 9348 // Copy elements backing store content. | 9524 // Copy elements backing store content. |
| 9349 if (elements->IsFixedDoubleArray()) { | 9525 if (elements->IsFixedDoubleArray()) { |
| 9350 BuildEmitFixedDoubleArray(elements, kind, object_elements); | 9526 BuildEmitFixedDoubleArray(elements, kind, object_elements); |
| 9351 } else if (elements->IsFixedArray()) { | 9527 } else if (elements->IsFixedArray()) { |
| 9352 BuildEmitFixedArray(elements, kind, object_elements, | 9528 BuildEmitFixedArray(elements, kind, object_elements, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 9373 value_instruction, kind); | 9549 value_instruction, kind); |
| 9374 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 9550 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 9375 } | 9551 } |
| 9376 } | 9552 } |
| 9377 | 9553 |
| 9378 | 9554 |
| 9379 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 9555 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| 9380 Handle<FixedArrayBase> elements, | 9556 Handle<FixedArrayBase> elements, |
| 9381 ElementsKind kind, | 9557 ElementsKind kind, |
| 9382 HValue* object_elements, | 9558 HValue* object_elements, |
| 9383 AllocationSiteContext* site_context) { | 9559 AllocationSiteUsageContext* site_context) { |
| 9384 HInstruction* boilerplate_elements = Add<HConstant>(elements); | 9560 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| 9385 int elements_length = elements->length(); | 9561 int elements_length = elements->length(); |
| 9386 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 9562 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 9387 for (int i = 0; i < elements_length; i++) { | 9563 for (int i = 0; i < elements_length; i++) { |
| 9388 Handle<Object> value(fast_elements->get(i), isolate()); | 9564 Handle<Object> value(fast_elements->get(i), isolate()); |
| 9389 HValue* key_constant = Add<HConstant>(i); | 9565 HValue* key_constant = Add<HConstant>(i); |
| 9390 if (value->IsJSObject()) { | 9566 if (value->IsJSObject()) { |
| 9391 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 9567 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 9392 Handle<AllocationSite> current_site = site_context->EnterNewScope(); | 9568 Handle<AllocationSite> current_site = site_context->EnterNewScope(); |
| 9393 HInstruction* result = | 9569 HInstruction* result = |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9846 } | 10022 } |
| 9847 | 10023 |
| 9848 | 10024 |
| 9849 // Fast support for StringAdd. | 10025 // Fast support for StringAdd. |
| 9850 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 10026 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 9851 ASSERT_EQ(2, call->arguments()->length()); | 10027 ASSERT_EQ(2, call->arguments()->length()); |
| 9852 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10028 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9853 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 10029 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9854 HValue* right = Pop(); | 10030 HValue* right = Pop(); |
| 9855 HValue* left = Pop(); | 10031 HValue* left = Pop(); |
| 9856 HInstruction* result = New<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH); | 10032 HInstruction* result = |
| 10033 NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH); |
| 9857 return ast_context()->ReturnInstruction(result, call->id()); | 10034 return ast_context()->ReturnInstruction(result, call->id()); |
| 9858 } | 10035 } |
| 9859 | 10036 |
| 9860 | 10037 |
| 9861 // Fast support for SubString. | 10038 // Fast support for SubString. |
| 9862 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 10039 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 9863 ASSERT_EQ(3, call->arguments()->length()); | 10040 ASSERT_EQ(3, call->arguments()->length()); |
| 9864 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 10041 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9865 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 10042 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
| 9866 Drop(3); | 10043 Drop(3); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9975 result->set_transcendental_type(TranscendentalCache::LOG); | 10152 result->set_transcendental_type(TranscendentalCache::LOG); |
| 9976 Drop(1); | 10153 Drop(1); |
| 9977 return ast_context()->ReturnInstruction(result, call->id()); | 10154 return ast_context()->ReturnInstruction(result, call->id()); |
| 9978 } | 10155 } |
| 9979 | 10156 |
| 9980 | 10157 |
| 9981 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 10158 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
| 9982 ASSERT(call->arguments()->length() == 1); | 10159 ASSERT(call->arguments()->length() == 1); |
| 9983 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10160 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9984 HValue* value = Pop(); | 10161 HValue* value = Pop(); |
| 9985 HInstruction* result = New<HUnaryMathOperation>(value, kMathSqrt); | 10162 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); |
| 9986 return ast_context()->ReturnInstruction(result, call->id()); | 10163 return ast_context()->ReturnInstruction(result, call->id()); |
| 9987 } | 10164 } |
| 9988 | 10165 |
| 9989 | 10166 |
| 9990 // Check whether two RegExps are equivalent | 10167 // Check whether two RegExps are equivalent |
| 9991 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 10168 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
| 9992 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); | 10169 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); |
| 9993 } | 10170 } |
| 9994 | 10171 |
| 9995 | 10172 |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10316 stream->Add("\n"); | 10493 stream->Add("\n"); |
| 10317 } | 10494 } |
| 10318 PrintF("\n"); | 10495 PrintF("\n"); |
| 10319 } | 10496 } |
| 10320 | 10497 |
| 10321 | 10498 |
| 10322 void HEnvironment::PrintToStd() { | 10499 void HEnvironment::PrintToStd() { |
| 10323 HeapStringAllocator string_allocator; | 10500 HeapStringAllocator string_allocator; |
| 10324 StringStream trace(&string_allocator); | 10501 StringStream trace(&string_allocator); |
| 10325 PrintTo(&trace); | 10502 PrintTo(&trace); |
| 10326 PrintF("%s", *trace.ToCString()); | 10503 PrintF("%s", trace.ToCString().get()); |
| 10327 } | 10504 } |
| 10328 | 10505 |
| 10329 | 10506 |
| 10330 void HTracer::TraceCompilation(CompilationInfo* info) { | 10507 void HTracer::TraceCompilation(CompilationInfo* info) { |
| 10331 Tag tag(this, "compilation"); | 10508 Tag tag(this, "compilation"); |
| 10332 if (info->IsOptimizing()) { | 10509 if (info->IsOptimizing()) { |
| 10333 Handle<String> name = info->function()->debug_name(); | 10510 Handle<String> name = info->function()->debug_name(); |
| 10334 PrintStringProperty("name", *name->ToCString()); | 10511 PrintStringProperty("name", name->ToCString().get()); |
| 10335 PrintStringProperty("method", *name->ToCString()); | 10512 PrintStringProperty("method", name->ToCString().get()); |
| 10336 } else { | 10513 } else { |
| 10337 CodeStub::Major major_key = info->code_stub()->MajorKey(); | 10514 CodeStub::Major major_key = info->code_stub()->MajorKey(); |
| 10338 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); | 10515 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); |
| 10339 PrintStringProperty("method", "stub"); | 10516 PrintStringProperty("method", "stub"); |
| 10340 } | 10517 } |
| 10341 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); | 10518 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); |
| 10342 } | 10519 } |
| 10343 | 10520 |
| 10344 | 10521 |
| 10345 void HTracer::TraceLithium(const char* name, LChunk* chunk) { | 10522 void HTracer::TraceLithium(const char* name, LChunk* chunk) { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10545 } | 10722 } |
| 10546 current_pos = current_pos->next(); | 10723 current_pos = current_pos->next(); |
| 10547 } | 10724 } |
| 10548 | 10725 |
| 10549 trace_.Add(" \"\"\n"); | 10726 trace_.Add(" \"\"\n"); |
| 10550 } | 10727 } |
| 10551 } | 10728 } |
| 10552 | 10729 |
| 10553 | 10730 |
| 10554 void HTracer::FlushToFile() { | 10731 void HTracer::FlushToFile() { |
| 10555 AppendChars(filename_.start(), *trace_.ToCString(), trace_.length(), false); | 10732 AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(), |
| 10733 false); |
| 10556 trace_.Reset(); | 10734 trace_.Reset(); |
| 10557 } | 10735 } |
| 10558 | 10736 |
| 10559 | 10737 |
| 10560 void HStatistics::Initialize(CompilationInfo* info) { | 10738 void HStatistics::Initialize(CompilationInfo* info) { |
| 10561 if (info->shared_info().is_null()) return; | 10739 if (info->shared_info().is_null()) return; |
| 10562 source_size_ += info->shared_info()->SourceSize(); | 10740 source_size_ += info->shared_info()->SourceSize(); |
| 10563 } | 10741 } |
| 10564 | 10742 |
| 10565 | 10743 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10635 if (ShouldProduceTraceOutput()) { | 10813 if (ShouldProduceTraceOutput()) { |
| 10636 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10814 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 10637 } | 10815 } |
| 10638 | 10816 |
| 10639 #ifdef DEBUG | 10817 #ifdef DEBUG |
| 10640 graph_->Verify(false); // No full verify. | 10818 graph_->Verify(false); // No full verify. |
| 10641 #endif | 10819 #endif |
| 10642 } | 10820 } |
| 10643 | 10821 |
| 10644 } } // namespace v8::internal | 10822 } } // namespace v8::internal |
| OLD | NEW |