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 1891 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1902 elements, isolate()->factory()->fixed_array_map(), top_info()); | 1902 elements, isolate()->factory()->fixed_array_map(), top_info()); |
1903 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1903 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1904 } | 1904 } |
1905 } | 1905 } |
1906 } | 1906 } |
1907 return AddElementAccess(elements, checked_key, val, checked_object, | 1907 return AddElementAccess(elements, checked_key, val, checked_object, |
1908 elements_kind, is_store, load_mode); | 1908 elements_kind, is_store, load_mode); |
1909 } | 1909 } |
1910 | 1910 |
1911 | 1911 |
1912 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind, | |
1913 HValue* capacity) { | |
1914 HValue* actual_capacity = capacity->ActualValue(); | |
1915 | |
1916 if (actual_capacity->IsInteger32Constant()) { | |
1917 int length = HConstant::cast(actual_capacity)->GetInteger32Constant(); | |
1918 int base_size = IsFastDoubleElementsKind(kind) | |
1919 ? FixedDoubleArray::SizeFor(length) | |
1920 : FixedArray::SizeFor(length); | |
1921 | |
1922 return Add<HConstant>(base_size); | |
1923 | |
1924 } else { | |
1925 int elements_size = IsFastDoubleElementsKind(kind) | |
mvstanton
2013/11/14 10:04:20
I just ran into a similar situation. Constant-fold
Igor Sheludko
2013/11/27 12:52:01
On 2013/11/14 10:04:20, mvstanton wrote:
Ok, I rem
| |
1926 ? kDoubleSize | |
1927 : kPointerSize; | |
1928 | |
1929 HConstant* elements_size_value = Add<HConstant>(elements_size); | |
1930 HValue* mul = Add<HMul>(capacity, elements_size_value); | |
1931 mul->ClearFlag(HValue::kCanOverflow); | |
1932 | |
1933 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); | |
1934 HValue* total_size = Add<HAdd>(mul, header_size); | |
1935 total_size->ClearFlag(HValue::kCanOverflow); | |
1936 return total_size; | |
1937 } | |
1938 } | |
1939 | |
1912 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, | 1940 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
1913 HValue* capacity) { | 1941 HValue* size_in_bytes, |
1914 int elements_size; | 1942 PretenureFlag pretenure) { |
1915 InstanceType instance_type; | 1943 InstanceType instance_type = IsFastDoubleElementsKind(kind) |
1944 ? FIXED_DOUBLE_ARRAY_TYPE | |
1945 : FIXED_ARRAY_TYPE; | |
1916 | 1946 |
1917 if (IsFastDoubleElementsKind(kind)) { | 1947 return Add<HAllocate>(size_in_bytes, HType::JSArray(), |
1918 elements_size = kDoubleSize; | 1948 pretenure, instance_type); |
1919 instance_type = FIXED_DOUBLE_ARRAY_TYPE; | |
1920 } else { | |
1921 elements_size = kPointerSize; | |
1922 instance_type = FIXED_ARRAY_TYPE; | |
1923 } | |
1924 | |
1925 HConstant* elements_size_value = Add<HConstant>(elements_size); | |
1926 HValue* mul = Add<HMul>(capacity, elements_size_value); | |
1927 mul->ClearFlag(HValue::kCanOverflow); | |
1928 | |
1929 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); | |
1930 HValue* total_size = Add<HAdd>(mul, header_size); | |
1931 total_size->ClearFlag(HValue::kCanOverflow); | |
1932 | |
1933 return Add<HAllocate>(total_size, HType::JSArray(), | |
1934 isolate()->heap()->GetPretenureMode(), instance_type); | |
1935 } | 1949 } |
1936 | 1950 |
1937 | 1951 |
1938 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 1952 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
1939 ElementsKind kind, | 1953 ElementsKind kind, |
1940 HValue* capacity) { | 1954 HValue* capacity) { |
1941 Factory* factory = isolate()->factory(); | 1955 Factory* factory = isolate()->factory(); |
1942 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1956 Handle<Map> map = IsFastDoubleElementsKind(kind) |
1943 ? factory->fixed_double_array_map() | 1957 ? factory->fixed_double_array_map() |
1944 : factory->fixed_array_map(); | 1958 : factory->fixed_array_map(); |
1945 | 1959 |
1946 AddStoreMapConstant(elements, map); | 1960 AddStoreMapConstant(elements, map); |
1947 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), | 1961 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), |
1948 capacity); | 1962 capacity); |
1949 } | 1963 } |
1950 | 1964 |
1951 | 1965 |
1952 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 1966 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
1953 ElementsKind kind, | 1967 ElementsKind kind, |
1954 HValue* capacity) { | 1968 HValue* capacity) { |
1955 // The HForceRepresentation is to prevent possible deopt on int-smi | 1969 // The HForceRepresentation is to prevent possible deopt on int-smi |
1956 // conversion after allocation but before the new object fields are set. | 1970 // conversion after allocation but before the new object fields are set. |
1957 capacity = Add<HForceRepresentation>(capacity, Representation::Smi()); | 1971 capacity = Add<HForceRepresentation>(capacity, Representation::Smi()); |
1958 HValue* new_elements = BuildAllocateElements(kind, capacity); | 1972 HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity); |
1973 HValue* new_elements = BuildAllocateElements( | |
1974 kind, size_in_bytes, isolate()->heap()->GetPretenureMode()); | |
1959 BuildInitializeElementsHeader(new_elements, kind, capacity); | 1975 BuildInitializeElementsHeader(new_elements, kind, capacity); |
1960 return new_elements; | 1976 return new_elements; |
1961 } | 1977 } |
1962 | 1978 |
1963 | 1979 |
1964 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1980 void HGraphBuilder::BuildJSArrayHeader(HValue* array, |
1965 HValue* array_map, | 1981 HValue* array_map, |
1966 AllocationSiteMode mode, | 1982 AllocationSiteMode mode, |
1967 ElementsKind elements_kind, | 1983 ElementsKind elements_kind, |
1968 HValue* allocation_site_payload, | 1984 HValue* allocation_site_payload, |
1969 HValue* length_field) { | 1985 HValue* length_field) { |
1970 | |
1971 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); | 1986 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); |
1972 | 1987 |
1973 HConstant* empty_fixed_array = | 1988 HConstant* empty_fixed_array = |
1974 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 1989 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
1975 | 1990 |
1976 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 1991 Add<HStoreNamedField>( |
1977 Add<HStoreNamedField>(array, access, empty_fixed_array); | 1992 array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array); |
1978 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), | 1993 |
1979 length_field); | 1994 Add<HStoreNamedField>( |
1995 array, HObjectAccess::ForElementsPointer(), empty_fixed_array); | |
1996 | |
1997 Add<HStoreNamedField>( | |
1998 array, HObjectAccess::ForArrayLength(elements_kind), length_field); | |
1980 | 1999 |
1981 if (mode == TRACK_ALLOCATION_SITE) { | 2000 if (mode == TRACK_ALLOCATION_SITE) { |
1982 BuildCreateAllocationMemento(array, | 2001 BuildCreateAllocationMemento(array, |
1983 JSArray::kSize, | 2002 JSArray::kSize, |
1984 allocation_site_payload); | 2003 allocation_site_payload); |
1985 } | 2004 } |
1986 | |
1987 int elements_location = JSArray::kSize; | |
1988 if (mode == TRACK_ALLOCATION_SITE) { | |
1989 elements_location += AllocationMemento::kSize; | |
1990 } | |
1991 | |
1992 HValue* elements = Add<HInnerAllocatedObject>(array, elements_location); | |
1993 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); | |
1994 return static_cast<HInnerAllocatedObject*>(elements); | |
1995 } | 2005 } |
1996 | 2006 |
1997 | 2007 |
1998 HInstruction* HGraphBuilder::AddElementAccess( | 2008 HInstruction* HGraphBuilder::AddElementAccess( |
1999 HValue* elements, | 2009 HValue* elements, |
2000 HValue* checked_key, | 2010 HValue* checked_key, |
2001 HValue* val, | 2011 HValue* val, |
2002 HValue* dependency, | 2012 HValue* dependency, |
2003 ElementsKind elements_kind, | 2013 ElementsKind elements_kind, |
2004 bool is_store, | 2014 bool is_store, |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2399 } | 2409 } |
2400 | 2410 |
2401 | 2411 |
2402 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 2412 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
2403 // Find the map near the constructor function | 2413 // Find the map near the constructor function |
2404 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 2414 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
2405 return builder()->AddLoadNamedField(constructor_function_, access); | 2415 return builder()->AddLoadNamedField(constructor_function_, access); |
2406 } | 2416 } |
2407 | 2417 |
2408 | 2418 |
2409 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 2419 HValue* HGraphBuilder::JSArrayBuilder::EstablishHeaderAllocationSize() { |
2410 HValue* length_node) { | |
2411 ASSERT(length_node != NULL); | |
2412 | |
2413 int base_size = JSArray::kSize; | 2420 int base_size = JSArray::kSize; |
2414 if (mode_ == TRACK_ALLOCATION_SITE) { | 2421 if (mode_ == TRACK_ALLOCATION_SITE) { |
2415 base_size += AllocationMemento::kSize; | 2422 base_size += AllocationMemento::kSize; |
2416 } | 2423 } |
2417 | |
2418 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); | |
2419 base_size += FixedArray::kHeaderSize; | |
2420 | |
2421 HInstruction* elements_size_value = | |
2422 builder()->Add<HConstant>(elements_size()); | |
2423 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value); | |
2424 mul->ClearFlag(HValue::kCanOverflow); | |
2425 | |
2426 HInstruction* base = builder()->Add<HConstant>(base_size); | |
2427 HInstruction* total_size = builder()->Add<HAdd>(base, mul); | |
2428 total_size->ClearFlag(HValue::kCanOverflow); | |
2429 return total_size; | |
2430 } | |
2431 | |
2432 | |
2433 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | |
2434 int base_size = JSArray::kSize; | |
2435 if (mode_ == TRACK_ALLOCATION_SITE) { | |
2436 base_size += AllocationMemento::kSize; | |
2437 } | |
2438 | |
2439 base_size += IsFastDoubleElementsKind(kind_) | |
2440 ? FixedDoubleArray::SizeFor(initial_capacity()) | |
2441 : FixedArray::SizeFor(initial_capacity()); | |
2442 | |
2443 return builder()->Add<HConstant>(base_size); | 2424 return builder()->Add<HConstant>(base_size); |
2444 } | 2425 } |
2445 | 2426 |
2446 | 2427 |
2447 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { | 2428 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { |
2448 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); | |
2449 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); | 2429 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); |
2450 return AllocateArray(size_in_bytes, | 2430 return AllocateArray(capacity, |
2451 capacity, | 2431 builder()->graph()->GetConstant0(), |
2452 builder()->graph()->GetConstant0(), | 2432 true); |
2453 true); | |
2454 } | 2433 } |
2455 | 2434 |
2456 | 2435 |
2457 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, | 2436 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, |
2458 HValue* length_field, | 2437 HValue* length_field, |
2459 bool fill_with_hole) { | 2438 bool fill_with_hole) { |
2460 HValue* size_in_bytes = EstablishAllocationSize(capacity); | |
2461 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); | |
2462 } | |
2463 | |
2464 | |
2465 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, | |
2466 HValue* capacity, | |
2467 HValue* length_field, | |
2468 bool fill_with_hole) { | |
2469 // These HForceRepresentations are because we store these as fields in the | 2439 // These HForceRepresentations are because we store these as fields in the |
2470 // objects we construct, and an int32-to-smi HChange could deopt. Accept | 2440 // objects we construct, and an int32-to-smi HChange could deopt. Accept |
2471 // the deopt possibility now, before allocation occurs. | 2441 // the deopt possibility now, before allocation occurs. |
2472 capacity = builder()->Add<HForceRepresentation>(capacity, | 2442 capacity = builder()->Add<HForceRepresentation>(capacity, |
2473 Representation::Smi()); | 2443 Representation::Smi()); |
2474 length_field = builder()->Add<HForceRepresentation>(length_field, | 2444 length_field = builder()->Add<HForceRepresentation>(length_field, |
2475 Representation::Smi()); | 2445 Representation::Smi()); |
2446 | |
2447 // Generate size calculation code here in order to make it dominate | |
2448 // the JSArray allocation. | |
mvstanton
2013/11/14 10:04:20
Nice.
Igor Sheludko
2013/11/27 12:52:01
Done.
| |
2449 HValue* elms_size = builder()->BuildCalculateElementsSize(kind_, capacity); | |
2450 | |
2476 // Allocate (dealing with failure appropriately) | 2451 // Allocate (dealing with failure appropriately) |
2477 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, | 2452 HValue* array_object_size = EstablishHeaderAllocationSize(); |
2453 HAllocate* array_object = builder()->Add<HAllocate>(array_object_size, | |
2478 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); | 2454 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); |
2479 | 2455 |
2480 // Folded array allocation should be aligned if it has fast double elements. | |
2481 if (IsFastDoubleElementsKind(kind_)) { | |
2482 new_object->MakeDoubleAligned(); | |
mvstanton
2013/11/14 10:04:20
Why was this removed, is it handled during the fol
Igor Sheludko
2013/11/27 12:52:01
This flag is set in the constructor of the HAlloca
| |
2483 } | |
2484 | |
2485 // Fill in the fields: map, properties, length | 2456 // Fill in the fields: map, properties, length |
2486 HValue* map; | 2457 HValue* map; |
2487 if (allocation_site_payload_ == NULL) { | 2458 if (allocation_site_payload_ == NULL) { |
2488 map = EmitInternalMapCode(); | 2459 map = EmitInternalMapCode(); |
2489 } else { | 2460 } else { |
2490 map = EmitMapCode(); | 2461 map = EmitMapCode(); |
2491 } | 2462 } |
2492 elements_location_ = builder()->BuildJSArrayHeader(new_object, | |
2493 map, | |
2494 mode_, | |
2495 kind_, | |
2496 allocation_site_payload_, | |
2497 length_field); | |
2498 | 2463 |
2499 // Initialize the elements | 2464 builder()->BuildJSArrayHeader(array_object, |
2465 map, | |
2466 mode_, | |
2467 kind_, | |
2468 allocation_site_payload_, | |
2469 length_field); | |
2470 | |
2471 // Allocate and initialize the elements | |
2472 elements_location_ = | |
2473 builder()->BuildAllocateElements(kind_, elms_size, NOT_TENURED); | |
2474 | |
2500 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); | 2475 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); |
2501 | 2476 |
2477 // Set the elements | |
2478 builder()->Add<HStoreNamedField>( | |
2479 array_object, HObjectAccess::ForElementsPointer(), elements_location_); | |
2480 | |
mvstanton
2013/11/14 10:04:20
Can you verify that a write barrier isn't used for
Igor Sheludko
2013/11/27 12:52:01
If two allocations folds together then the second
| |
2502 if (fill_with_hole) { | 2481 if (fill_with_hole) { |
2503 builder()->BuildFillElementsWithHole(elements_location_, kind_, | 2482 builder()->BuildFillElementsWithHole(elements_location_, kind_, |
2504 graph()->GetConstant0(), capacity); | 2483 graph()->GetConstant0(), capacity); |
2505 } | 2484 } |
2506 | 2485 |
2507 return new_object; | 2486 return array_object; |
2508 } | 2487 } |
2509 | 2488 |
2510 | 2489 |
2511 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 2490 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
2512 Handle<Map> map) { | 2491 Handle<Map> map) { |
2513 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), | 2492 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), |
2514 Add<HConstant>(map)); | 2493 Add<HConstant>(map)); |
2515 } | 2494 } |
2516 | 2495 |
2517 | 2496 |
(...skipping 7650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10168 if (ShouldProduceTraceOutput()) { | 10147 if (ShouldProduceTraceOutput()) { |
10169 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10148 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10170 } | 10149 } |
10171 | 10150 |
10172 #ifdef DEBUG | 10151 #ifdef DEBUG |
10173 graph_->Verify(false); // No full verify. | 10152 graph_->Verify(false); // No full verify. |
10174 #endif | 10153 #endif |
10175 } | 10154 } |
10176 | 10155 |
10177 } } // namespace v8::internal | 10156 } } // namespace v8::internal |
OLD | NEW |