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

Side by Side Diff: src/hydrogen.cc

Issue 61463005: Supported folding of constant size allocation followed by dynamic size allocation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Allocation folding of const + dynamic sizes case. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/hydrogen-instructions.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698