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 |
| 1913 HValue* HGraphBuilder::BuildAllocateArrayFromLength( |
| 1914 JSArrayBuilder* array_builder, |
| 1915 HValue* length_argument) { |
| 1916 if (length_argument->IsConstant() && |
| 1917 HConstant::cast(length_argument)->HasSmiValue()) { |
| 1918 int array_length = HConstant::cast(length_argument)->Integer32Value(); |
| 1919 HValue* new_object = array_length == 0 |
| 1920 ? array_builder->AllocateEmptyArray() |
| 1921 : array_builder->AllocateArray(length_argument, length_argument); |
| 1922 return new_object; |
| 1923 } |
| 1924 |
| 1925 HValue* constant_zero = graph()->GetConstant0(); |
| 1926 HConstant* max_alloc_length = |
| 1927 Add<HConstant>(JSObject::kInitialMaxFastElementArray); |
| 1928 HInstruction* checked_length = Add<HBoundsCheck>(length_argument, |
| 1929 max_alloc_length); |
| 1930 IfBuilder if_builder(this); |
| 1931 if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero, |
| 1932 Token::EQ); |
| 1933 if_builder.Then(); |
| 1934 const int initial_capacity = JSArray::kPreallocatedArrayElements; |
| 1935 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity); |
| 1936 Push(initial_capacity_node); // capacity |
| 1937 Push(constant_zero); // length |
| 1938 if_builder.Else(); |
| 1939 if (!(top_info()->IsStub()) && |
| 1940 IsFastPackedElementsKind(array_builder->kind())) { |
| 1941 // We'll come back later with better (holey) feedback. |
| 1942 if_builder.Deopt("Holey array despite packed elements_kind feedback"); |
| 1943 } |
| 1944 Push(checked_length); // capacity |
| 1945 Push(checked_length); // length |
| 1946 if_builder.End(); |
| 1947 |
| 1948 // Figure out total size |
| 1949 HValue* length = Pop(); |
| 1950 HValue* capacity = Pop(); |
| 1951 return array_builder->AllocateArray(capacity, length); |
| 1952 } |
| 1953 |
1912 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, | 1954 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
1913 HValue* capacity) { | 1955 HValue* capacity) { |
1914 int elements_size; | 1956 int elements_size; |
1915 InstanceType instance_type; | 1957 InstanceType instance_type; |
1916 | 1958 |
1917 if (IsFastDoubleElementsKind(kind)) { | 1959 if (IsFastDoubleElementsKind(kind)) { |
1918 elements_size = kDoubleSize; | 1960 elements_size = kDoubleSize; |
1919 instance_type = FIXED_DOUBLE_ARRAY_TYPE; | 1961 instance_type = FIXED_DOUBLE_ARRAY_TYPE; |
1920 } else { | 1962 } else { |
1921 elements_size = kPointerSize; | 1963 elements_size = kPointerSize; |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2090 // Fast elements kinds need to be initialized in case statements below cause | 2132 // Fast elements kinds need to be initialized in case statements below cause |
2091 // a garbage collection. | 2133 // a garbage collection. |
2092 Factory* factory = isolate()->factory(); | 2134 Factory* factory = isolate()->factory(); |
2093 | 2135 |
2094 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 2136 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
2095 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 2137 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
2096 ? Add<HConstant>(factory->the_hole_value()) | 2138 ? Add<HConstant>(factory->the_hole_value()) |
2097 : Add<HConstant>(nan_double); | 2139 : Add<HConstant>(nan_double); |
2098 | 2140 |
2099 // Special loop unfolding case | 2141 // Special loop unfolding case |
2100 static const int kLoopUnfoldLimit = 4; | 2142 static const int kLoopUnfoldLimit = 8; |
2101 bool unfold_loop = false; | 2143 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); |
2102 int initial_capacity = JSArray::kPreallocatedArrayElements; | 2144 int initial_capacity = -1; |
2103 if (from->ActualValue()->IsConstant() && to->ActualValue()->IsConstant() && | 2145 if (from->ActualValue()->IsConstant() && to->ActualValue()->IsConstant()) { |
2104 initial_capacity <= kLoopUnfoldLimit) { | |
2105 HConstant* constant_from = HConstant::cast(from->ActualValue()); | 2146 HConstant* constant_from = HConstant::cast(from->ActualValue()); |
2106 HConstant* constant_to = HConstant::cast(to->ActualValue()); | 2147 HConstant* constant_to = HConstant::cast(to->ActualValue()); |
2107 | 2148 |
2108 if (constant_from->HasInteger32Value() && | 2149 if (constant_from->HasInteger32Value() && |
2109 constant_from->Integer32Value() == 0 && | 2150 constant_from->Integer32Value() == 0 && |
2110 constant_to->HasInteger32Value() && | 2151 constant_to->HasInteger32Value() && |
2111 constant_to->Integer32Value() == initial_capacity) { | 2152 constant_to->Integer32Value() <= kLoopUnfoldLimit) { |
2112 unfold_loop = true; | 2153 initial_capacity = constant_to->Integer32Value(); |
2113 } | 2154 } |
2114 } | 2155 } |
2115 | 2156 |
2116 // Since we're about to store a hole value, the store instruction below must | 2157 // Since we're about to store a hole value, the store instruction below must |
2117 // assume an elements kind that supports heap object values. | 2158 // assume an elements kind that supports heap object values. |
2118 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 2159 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
2119 elements_kind = FAST_HOLEY_ELEMENTS; | 2160 elements_kind = FAST_HOLEY_ELEMENTS; |
2120 } | 2161 } |
2121 | 2162 |
2122 if (unfold_loop) { | 2163 if (initial_capacity >= 0) { |
2123 for (int i = 0; i < initial_capacity; i++) { | 2164 for (int i = 0; i < initial_capacity; i++) { |
2124 HInstruction* key = Add<HConstant>(i); | 2165 HInstruction* key = Add<HConstant>(i); |
2125 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2166 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
2126 } | 2167 } |
2127 } else { | 2168 } else { |
2128 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); | 2169 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
2129 | 2170 |
2130 HValue* key = builder.BeginBody(from, to, Token::LT); | 2171 HValue* key = builder.BeginBody(from, to, Token::LT); |
2131 | 2172 |
2132 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2173 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2371 HValue* constructor_function) : | 2412 HValue* constructor_function) : |
2372 builder_(builder), | 2413 builder_(builder), |
2373 kind_(kind), | 2414 kind_(kind), |
2374 mode_(DONT_TRACK_ALLOCATION_SITE), | 2415 mode_(DONT_TRACK_ALLOCATION_SITE), |
2375 allocation_site_payload_(NULL), | 2416 allocation_site_payload_(NULL), |
2376 constructor_function_(constructor_function) { | 2417 constructor_function_(constructor_function) { |
2377 } | 2418 } |
2378 | 2419 |
2379 | 2420 |
2380 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { | 2421 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { |
| 2422 if (!builder()->top_info()->IsStub()) { |
| 2423 // A constant map is fine. |
| 2424 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_), |
| 2425 builder()->isolate()); |
| 2426 return builder()->Add<HConstant>(map); |
| 2427 } |
| 2428 |
2381 if (kind_ == GetInitialFastElementsKind()) { | 2429 if (kind_ == GetInitialFastElementsKind()) { |
2382 // No need for a context lookup if the kind_ matches the initial | 2430 // No need for a context lookup if the kind_ matches the initial |
2383 // map, because we can just load the map in that case. | 2431 // map, because we can just load the map in that case. |
2384 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 2432 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
2385 return builder()->AddLoadNamedField(constructor_function_, access); | 2433 return builder()->AddLoadNamedField(constructor_function_, access); |
2386 } | 2434 } |
2387 | 2435 |
2388 HInstruction* native_context = builder()->BuildGetNativeContext(); | 2436 HInstruction* native_context = builder()->BuildGetNativeContext(); |
2389 HInstruction* index = builder()->Add<HConstant>( | 2437 HInstruction* index = builder()->Add<HConstant>( |
2390 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 2438 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
(...skipping 22 matching lines...) Expand all Loading... |
2413 int base_size = JSArray::kSize; | 2461 int base_size = JSArray::kSize; |
2414 if (mode_ == TRACK_ALLOCATION_SITE) { | 2462 if (mode_ == TRACK_ALLOCATION_SITE) { |
2415 base_size += AllocationMemento::kSize; | 2463 base_size += AllocationMemento::kSize; |
2416 } | 2464 } |
2417 | 2465 |
2418 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); | 2466 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
2419 base_size += FixedArray::kHeaderSize; | 2467 base_size += FixedArray::kHeaderSize; |
2420 | 2468 |
2421 HInstruction* elements_size_value = | 2469 HInstruction* elements_size_value = |
2422 builder()->Add<HConstant>(elements_size()); | 2470 builder()->Add<HConstant>(elements_size()); |
2423 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value); | 2471 HInstruction* mul = HMul::NewImul(builder()->zone(), builder()->context(), |
2424 mul->ClearFlag(HValue::kCanOverflow); | 2472 length_node, elements_size_value); |
2425 | 2473 builder()->AddInstruction(mul); |
2426 HInstruction* base = builder()->Add<HConstant>(base_size); | 2474 HInstruction* base = builder()->Add<HConstant>(base_size); |
2427 HInstruction* total_size = builder()->Add<HAdd>(base, mul); | 2475 HInstruction* total_size = HAdd::New(builder()->zone(), builder()->context(), |
| 2476 base, mul); |
2428 total_size->ClearFlag(HValue::kCanOverflow); | 2477 total_size->ClearFlag(HValue::kCanOverflow); |
| 2478 builder()->AddInstruction(total_size); |
2429 return total_size; | 2479 return total_size; |
2430 } | 2480 } |
2431 | 2481 |
2432 | 2482 |
2433 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | 2483 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { |
2434 int base_size = JSArray::kSize; | 2484 int base_size = JSArray::kSize; |
2435 if (mode_ == TRACK_ALLOCATION_SITE) { | 2485 if (mode_ == TRACK_ALLOCATION_SITE) { |
2436 base_size += AllocationMemento::kSize; | 2486 base_size += AllocationMemento::kSize; |
2437 } | 2487 } |
2438 | 2488 |
2439 base_size += IsFastDoubleElementsKind(kind_) | 2489 base_size += IsFastDoubleElementsKind(kind_) |
2440 ? FixedDoubleArray::SizeFor(initial_capacity()) | 2490 ? FixedDoubleArray::SizeFor(initial_capacity()) |
2441 : FixedArray::SizeFor(initial_capacity()); | 2491 : FixedArray::SizeFor(initial_capacity()); |
2442 | 2492 |
2443 return builder()->Add<HConstant>(base_size); | 2493 return builder()->Add<HConstant>(base_size); |
2444 } | 2494 } |
2445 | 2495 |
2446 | 2496 |
2447 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { | 2497 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { |
2448 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); | 2498 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); |
2449 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); | 2499 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); |
2450 return AllocateArray(size_in_bytes, | 2500 return AllocateArray(size_in_bytes, |
2451 capacity, | 2501 capacity, |
2452 builder()->graph()->GetConstant0(), | 2502 builder()->graph()->GetConstant0()); |
2453 true); | |
2454 } | 2503 } |
2455 | 2504 |
2456 | 2505 |
2457 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, | 2506 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, |
2458 HValue* length_field, | 2507 HValue* length_field, |
2459 bool fill_with_hole) { | 2508 FillMode fill_mode) { |
2460 HValue* size_in_bytes = EstablishAllocationSize(capacity); | 2509 HValue* size_in_bytes = EstablishAllocationSize(capacity); |
2461 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); | 2510 return AllocateArray(size_in_bytes, capacity, length_field, fill_mode); |
2462 } | 2511 } |
2463 | 2512 |
2464 | 2513 |
2465 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, | 2514 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, |
2466 HValue* capacity, | 2515 HValue* capacity, |
2467 HValue* length_field, | 2516 HValue* length_field, |
2468 bool fill_with_hole) { | 2517 FillMode fill_mode) { |
2469 // These HForceRepresentations are because we store these as fields in the | 2518 // These HForceRepresentations are because we store these as fields in the |
2470 // objects we construct, and an int32-to-smi HChange could deopt. Accept | 2519 // objects we construct, and an int32-to-smi HChange could deopt. Accept |
2471 // the deopt possibility now, before allocation occurs. | 2520 // the deopt possibility now, before allocation occurs. |
2472 capacity = builder()->Add<HForceRepresentation>(capacity, | 2521 capacity = builder()->Add<HForceRepresentation>(capacity, |
2473 Representation::Smi()); | 2522 Representation::Smi()); |
2474 length_field = builder()->Add<HForceRepresentation>(length_field, | 2523 length_field = builder()->Add<HForceRepresentation>(length_field, |
2475 Representation::Smi()); | 2524 Representation::Smi()); |
2476 // Allocate (dealing with failure appropriately) | 2525 // Allocate (dealing with failure appropriately) |
2477 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, | 2526 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, |
2478 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); | 2527 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); |
(...skipping 13 matching lines...) Expand all Loading... |
2492 elements_location_ = builder()->BuildJSArrayHeader(new_object, | 2541 elements_location_ = builder()->BuildJSArrayHeader(new_object, |
2493 map, | 2542 map, |
2494 mode_, | 2543 mode_, |
2495 kind_, | 2544 kind_, |
2496 allocation_site_payload_, | 2545 allocation_site_payload_, |
2497 length_field); | 2546 length_field); |
2498 | 2547 |
2499 // Initialize the elements | 2548 // Initialize the elements |
2500 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); | 2549 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); |
2501 | 2550 |
2502 if (fill_with_hole) { | 2551 if (fill_mode == FILL_WITH_HOLE) { |
2503 builder()->BuildFillElementsWithHole(elements_location_, kind_, | 2552 builder()->BuildFillElementsWithHole(elements_location_, kind_, |
2504 graph()->GetConstant0(), capacity); | 2553 graph()->GetConstant0(), capacity); |
2505 } | 2554 } |
2506 | 2555 |
2507 return new_object; | 2556 return new_object; |
2508 } | 2557 } |
2509 | 2558 |
2510 | 2559 |
2511 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 2560 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
2512 Handle<Map> map) { | 2561 Handle<Map> map) { |
(...skipping 5015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7528 | 7577 |
7529 call = New<HCallFunction>(function, argument_count); | 7578 call = New<HCallFunction>(function, argument_count); |
7530 Drop(argument_count + 1); | 7579 Drop(argument_count + 1); |
7531 } | 7580 } |
7532 } | 7581 } |
7533 | 7582 |
7534 return ast_context()->ReturnInstruction(call, expr->id()); | 7583 return ast_context()->ReturnInstruction(call, expr->id()); |
7535 } | 7584 } |
7536 | 7585 |
7537 | 7586 |
| 7587 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { |
| 7588 NoObservableSideEffectsScope no_effects(this); |
| 7589 |
| 7590 int argument_count = expr->arguments()->length(); |
| 7591 // We should at least have the constructor on the expression stack. |
| 7592 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
| 7593 |
| 7594 ElementsKind kind = expr->elements_kind(); |
| 7595 Handle<Cell> cell = expr->allocation_info_cell(); |
| 7596 AllocationSite* site = AllocationSite::cast(cell->value()); |
| 7597 |
| 7598 // Register on the site for deoptimization if the cell value changes. |
| 7599 site->AddDependentCompilationInfo(AllocationSite::TRANSITIONS, top_info()); |
| 7600 HInstruction* cell_instruction = Add<HConstant>(cell); |
| 7601 |
| 7602 // In the single constant argument case, we may have to adjust elements kind |
| 7603 // to avoid creating a packed non-empty array. |
| 7604 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { |
| 7605 HValue* argument = environment()->Top(); |
| 7606 if (argument->IsConstant()) { |
| 7607 HConstant* constant_argument = HConstant::cast(argument); |
| 7608 ASSERT(constant_argument->HasSmiValue()); |
| 7609 int constant_array_size = constant_argument->Integer32Value(); |
| 7610 if (constant_array_size != 0) { |
| 7611 kind = GetHoleyElementsKind(kind); |
| 7612 } |
| 7613 } |
| 7614 } |
| 7615 |
| 7616 // Build the array. |
| 7617 JSArrayBuilder array_builder(this, |
| 7618 kind, |
| 7619 cell_instruction, |
| 7620 constructor, |
| 7621 DISABLE_ALLOCATION_SITES); |
| 7622 HValue* new_object; |
| 7623 if (argument_count == 0) { |
| 7624 new_object = array_builder.AllocateEmptyArray(); |
| 7625 } else if (argument_count == 1) { |
| 7626 HValue* argument = environment()->Top(); |
| 7627 new_object = BuildAllocateArrayFromLength(&array_builder, argument); |
| 7628 } else { |
| 7629 HValue* length = Add<HConstant>(argument_count); |
| 7630 // Smi arrays need to initialize array elements with the hole because |
| 7631 // bailout could occur if the arguments don't fit in a smi. |
| 7632 // |
| 7633 // TODO(mvstanton): If all the arguments are constants in smi range, then |
| 7634 // we could set fill_with_hole to false and save a few instructions. |
| 7635 JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind) |
| 7636 ? JSArrayBuilder::FILL_WITH_HOLE |
| 7637 : JSArrayBuilder::DONT_FILL_WITH_HOLE; |
| 7638 new_object = array_builder.AllocateArray(length, length, fill_mode); |
| 7639 HValue* elements = array_builder.GetElementsLocation(); |
| 7640 for (int i = 0; i < argument_count; i++) { |
| 7641 HValue* value = environment()->ExpressionStackAt(argument_count - i - 1); |
| 7642 HValue* constant_i = Add<HConstant>(i); |
| 7643 Add<HStoreKeyed>(elements, constant_i, value, kind); |
| 7644 } |
| 7645 } |
| 7646 |
| 7647 Drop(argument_count + 1); // drop constructor and args. |
| 7648 ast_context()->ReturnValue(new_object); |
| 7649 } |
| 7650 |
| 7651 |
7538 // Checks whether allocation using the given constructor can be inlined. | 7652 // Checks whether allocation using the given constructor can be inlined. |
7539 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7653 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
7540 return constructor->has_initial_map() && | 7654 return constructor->has_initial_map() && |
7541 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7655 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
7542 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && | 7656 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && |
7543 constructor->initial_map()->InitialPropertiesLength() == 0; | 7657 constructor->initial_map()->InitialPropertiesLength() == 0; |
7544 } | 7658 } |
7545 | 7659 |
7546 | 7660 |
| 7661 bool HOptimizedGraphBuilder::IsCallNewArrayInlineable(CallNew* expr) { |
| 7662 bool inline_ok = false; |
| 7663 Handle<JSFunction> caller = current_info()->closure(); |
| 7664 Handle<JSFunction> target(isolate()->global_context()->array_function(), |
| 7665 isolate()); |
| 7666 int argument_count = expr->arguments()->length(); |
| 7667 // We should have the function plus array arguments on the environment stack. |
| 7668 ASSERT(environment()->length() >= (argument_count + 1)); |
| 7669 Handle<Cell> cell = expr->allocation_info_cell(); |
| 7670 AllocationSite* site = AllocationSite::cast(cell->value()); |
| 7671 if (site->CanInlineCall()) { |
| 7672 // We also want to avoid inlining in certain 1 argument scenarios. |
| 7673 if (argument_count == 1) { |
| 7674 HValue* argument = Top(); |
| 7675 if (argument->IsConstant()) { |
| 7676 // Do not inline if the constant length argument is not a smi or |
| 7677 // outside the valid range for a fast array. |
| 7678 HConstant* constant_argument = HConstant::cast(argument); |
| 7679 if (constant_argument->HasSmiValue()) { |
| 7680 int value = constant_argument->Integer32Value(); |
| 7681 inline_ok = value >= 0 && |
| 7682 value < JSObject::kInitialMaxFastElementArray; |
| 7683 if (!inline_ok) { |
| 7684 TraceInline(target, caller, |
| 7685 "Length outside of valid array range"); |
| 7686 } |
| 7687 } |
| 7688 } else { |
| 7689 inline_ok = true; |
| 7690 } |
| 7691 } else { |
| 7692 inline_ok = true; |
| 7693 } |
| 7694 } else { |
| 7695 TraceInline(target, caller, "AllocationSite requested no inlining."); |
| 7696 } |
| 7697 |
| 7698 if (inline_ok) { |
| 7699 TraceInline(target, caller, NULL); |
| 7700 } |
| 7701 return inline_ok; |
| 7702 } |
| 7703 |
| 7704 |
7547 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7705 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
7548 ASSERT(!HasStackOverflow()); | 7706 ASSERT(!HasStackOverflow()); |
7549 ASSERT(current_block() != NULL); | 7707 ASSERT(current_block() != NULL); |
7550 ASSERT(current_block()->HasPredecessor()); | 7708 ASSERT(current_block()->HasPredecessor()); |
7551 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); | 7709 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); |
7552 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7710 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
7553 Factory* factory = isolate()->factory(); | 7711 Factory* factory = isolate()->factory(); |
7554 | 7712 |
| 7713 // The constructor function is on the stack in the unoptimized code |
| 7714 // during evaluation of the arguments. |
| 7715 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7716 HValue* function = Top(); |
| 7717 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 7718 |
7555 if (FLAG_inline_construct && | 7719 if (FLAG_inline_construct && |
7556 expr->IsMonomorphic() && | 7720 expr->IsMonomorphic() && |
7557 IsAllocationInlineable(expr->target())) { | 7721 IsAllocationInlineable(expr->target())) { |
7558 // The constructor function is on the stack in the unoptimized code | |
7559 // during evaluation of the arguments. | |
7560 CHECK_ALIVE(VisitForValue(expr->expression())); | |
7561 HValue* function = Top(); | |
7562 CHECK_ALIVE(VisitExpressions(expr->arguments())); | |
7563 Handle<JSFunction> constructor = expr->target(); | 7722 Handle<JSFunction> constructor = expr->target(); |
7564 HValue* check = Add<HCheckValue>(function, constructor); | 7723 HValue* check = Add<HCheckValue>(function, constructor); |
7565 | 7724 |
7566 // Force completion of inobject slack tracking before generating | 7725 // Force completion of inobject slack tracking before generating |
7567 // allocation code to finalize instance size. | 7726 // allocation code to finalize instance size. |
7568 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { | 7727 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { |
7569 constructor->shared()->CompleteInobjectSlackTracking(); | 7728 constructor->shared()->CompleteInobjectSlackTracking(); |
7570 } | 7729 } |
7571 | 7730 |
7572 // Calculate instance size from initial map of constructor. | 7731 // Calculate instance size from initial map of constructor. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7639 check->DeleteAndReplaceWith(NULL); | 7798 check->DeleteAndReplaceWith(NULL); |
7640 environment()->SetExpressionStackAt(receiver_index, function); | 7799 environment()->SetExpressionStackAt(receiver_index, function); |
7641 HInstruction* call = | 7800 HInstruction* call = |
7642 PreProcessCall(New<HCallNew>(function, argument_count)); | 7801 PreProcessCall(New<HCallNew>(function, argument_count)); |
7643 return ast_context()->ReturnInstruction(call, expr->id()); | 7802 return ast_context()->ReturnInstruction(call, expr->id()); |
7644 } else { | 7803 } else { |
7645 // The constructor function is both an operand to the instruction and an | 7804 // The constructor function is both an operand to the instruction and an |
7646 // argument to the construct call. | 7805 // argument to the construct call. |
7647 Handle<JSFunction> array_function( | 7806 Handle<JSFunction> array_function( |
7648 isolate()->global_context()->array_function(), isolate()); | 7807 isolate()->global_context()->array_function(), isolate()); |
7649 CHECK_ALIVE(VisitArgument(expr->expression())); | 7808 bool use_call_new_array = expr->target().is_identical_to(array_function); |
7650 HValue* constructor = HPushArgument::cast(Top())->argument(); | 7809 Handle<Cell> cell = expr->allocation_info_cell(); |
7651 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7810 if (use_call_new_array && IsCallNewArrayInlineable(expr)) { |
| 7811 // Verify we are still calling the array function for our native context. |
| 7812 Add<HCheckValue>(function, array_function); |
| 7813 BuildInlinedCallNewArray(expr); |
| 7814 return; |
| 7815 } |
| 7816 |
7652 HBinaryCall* call; | 7817 HBinaryCall* call; |
7653 if (expr->target().is_identical_to(array_function)) { | 7818 if (use_call_new_array) { |
7654 Handle<Cell> cell = expr->allocation_info_cell(); | 7819 Add<HCheckValue>(function, array_function); |
7655 Add<HCheckValue>(constructor, array_function); | 7820 call = New<HCallNewArray>(function, argument_count, cell, |
7656 call = New<HCallNewArray>(constructor, argument_count, | 7821 expr->elements_kind()); |
7657 cell, expr->elements_kind()); | |
7658 } else { | 7822 } else { |
7659 call = New<HCallNew>(constructor, argument_count); | 7823 call = New<HCallNew>(function, argument_count); |
7660 } | 7824 } |
7661 Drop(argument_count); | 7825 PreProcessCall(call); |
7662 return ast_context()->ReturnInstruction(call, expr->id()); | 7826 return ast_context()->ReturnInstruction(call, expr->id()); |
7663 } | 7827 } |
7664 } | 7828 } |
7665 | 7829 |
7666 | 7830 |
7667 // Support for generating inlined runtime functions. | 7831 // Support for generating inlined runtime functions. |
7668 | 7832 |
7669 // Lookup table for generators for runtime calls that are generated inline. | 7833 // Lookup table for generators for runtime calls that are generated inline. |
7670 // Elements of the table are member pointers to functions of | 7834 // Elements of the table are member pointers to functions of |
7671 // HOptimizedGraphBuilder. | 7835 // HOptimizedGraphBuilder. |
(...skipping 2496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10168 if (ShouldProduceTraceOutput()) { | 10332 if (ShouldProduceTraceOutput()) { |
10169 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10333 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10170 } | 10334 } |
10171 | 10335 |
10172 #ifdef DEBUG | 10336 #ifdef DEBUG |
10173 graph_->Verify(false); // No full verify. | 10337 graph_->Verify(false); // No full verify. |
10174 #endif | 10338 #endif |
10175 } | 10339 } |
10176 | 10340 |
10177 } } // namespace v8::internal | 10341 } } // namespace v8::internal |
OLD | NEW |