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

Side by Side Diff: src/hydrogen.cc

Issue 55933002: Inline array constructor. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Added comment to CreateArrayDispatchOneArgument 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
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698