Chromium Code Reviews| 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 |