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

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: Comment response, inline tracing, and making HForceRepresentation idef 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 1540 matching lines...) Expand 10 before | Expand all | Expand 10 after
1551 elements, isolate()->factory()->fixed_array_map(), top_info()); 1551 elements, isolate()->factory()->fixed_array_map(), top_info());
1552 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1552 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1553 } 1553 }
1554 } 1554 }
1555 } 1555 }
1556 return AddElementAccess(elements, checked_key, val, checked_object, 1556 return AddElementAccess(elements, checked_key, val, checked_object,
1557 elements_kind, is_store, load_mode); 1557 elements_kind, is_store, load_mode);
1558 } 1558 }
1559 1559
1560 1560
1561
1562 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
1563 JSArrayBuilder* array_builder,
1564 HValue* length_argument) {
1565 if (length_argument->IsConstant() &&
1566 HConstant::cast(length_argument)->HasSmiValue()) {
1567 int array_length = HConstant::cast(length_argument)->Integer32Value();
1568 HValue* new_object = (array_length == 0)
Toon Verwaest 2013/11/11 13:59:28 Remove the parentheses.
mvstanton 2013/11/13 14:12:52 Done.
1569 ? array_builder->AllocateEmptyArray()
1570 : array_builder->AllocateArray(length_argument, length_argument);
1571 return new_object;
1572 }
1573
1574 HValue* constant_zero = graph()->GetConstant0();
1575 HConstant* max_alloc_length =
1576 Add<HConstant>(JSObject::kInitialMaxFastElementArray);
1577 const int initial_capacity = JSArray::kPreallocatedArrayElements;
1578 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
Toon Verwaest 2013/11/11 13:59:28 Move this down to the case where initial-capacity-
mvstanton 2013/11/13 14:12:52 Done.
1579 HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
1580 max_alloc_length);
1581 IfBuilder if_builder(this);
1582 if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
1583 Token::EQ);
1584 if_builder.Then();
1585 Push(initial_capacity_node); // capacity
1586 Push(constant_zero); // length
1587 if_builder.Else();
1588 Push(checked_length); // capacity
1589 Push(checked_length); // length
1590 if_builder.End();
1591
1592 // Figure out total size
1593 HValue* length = Pop();
1594 HValue* capacity = Pop();
1595 return array_builder->AllocateArray(capacity, length);
1596 }
1597
1561 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, 1598 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
1562 HValue* capacity) { 1599 HValue* capacity) {
1563 int elements_size; 1600 int elements_size;
1564 InstanceType instance_type; 1601 InstanceType instance_type;
1565 1602
1566 if (IsFastDoubleElementsKind(kind)) { 1603 if (IsFastDoubleElementsKind(kind)) {
1567 elements_size = kDoubleSize; 1604 elements_size = kDoubleSize;
1568 instance_type = FIXED_DOUBLE_ARRAY_TYPE; 1605 instance_type = FIXED_DOUBLE_ARRAY_TYPE;
1569 } else { 1606 } else {
1570 elements_size = kPointerSize; 1607 elements_size = kPointerSize;
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1739 // Fast elements kinds need to be initialized in case statements below cause 1776 // Fast elements kinds need to be initialized in case statements below cause
1740 // a garbage collection. 1777 // a garbage collection.
1741 Factory* factory = isolate()->factory(); 1778 Factory* factory = isolate()->factory();
1742 1779
1743 double nan_double = FixedDoubleArray::hole_nan_as_double(); 1780 double nan_double = FixedDoubleArray::hole_nan_as_double();
1744 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) 1781 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
1745 ? Add<HConstant>(factory->the_hole_value()) 1782 ? Add<HConstant>(factory->the_hole_value())
1746 : Add<HConstant>(nan_double); 1783 : Add<HConstant>(nan_double);
1747 1784
1748 // Special loop unfolding case 1785 // Special loop unfolding case
1749 static const int kLoopUnfoldLimit = 4; 1786 static const int kLoopUnfoldLimit = 6;
1750 bool unfold_loop = false; 1787 bool unfold_loop = false;
1751 int initial_capacity = JSArray::kPreallocatedArrayElements; 1788 int initial_capacity;
1752 if (from->IsConstant() && to->IsConstant() && 1789
1753 initial_capacity <= kLoopUnfoldLimit) { 1790 if (from->ActualValue()->IsConstant() && to->ActualValue()->IsConstant()) {
Toon Verwaest 2013/11/11 13:59:28 Please put this is a separate CL (that also more w
mvstanton 2013/11/13 14:12:52 I made another CL that isolates the idef of HForce
1754 HConstant* constant_from = HConstant::cast(from); 1791 HConstant* constant_from = HConstant::cast(from->ActualValue());
1755 HConstant* constant_to = HConstant::cast(to); 1792 HConstant* constant_to = HConstant::cast(to->ActualValue());
1756 1793
1757 if (constant_from->HasInteger32Value() && 1794 if (constant_from->HasInteger32Value() &&
1758 constant_from->Integer32Value() == 0 && 1795 constant_from->Integer32Value() == 0 &&
1759 constant_to->HasInteger32Value() && 1796 constant_to->HasInteger32Value() &&
1760 constant_to->Integer32Value() == initial_capacity) { 1797 constant_to->Integer32Value() <= kLoopUnfoldLimit) {
1761 unfold_loop = true; 1798 unfold_loop = true;
1799 initial_capacity = constant_to->Integer32Value();
1762 } 1800 }
1763 } 1801 }
1764 1802
1765 // Since we're about to store a hole value, the store instruction below must 1803 // Since we're about to store a hole value, the store instruction below must
1766 // assume an elements kind that supports heap object values. 1804 // assume an elements kind that supports heap object values.
1767 if (IsFastSmiOrObjectElementsKind(elements_kind)) { 1805 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
1768 elements_kind = FAST_HOLEY_ELEMENTS; 1806 elements_kind = FAST_HOLEY_ELEMENTS;
1769 } 1807 }
1770 1808
1771 if (unfold_loop) { 1809 if (unfold_loop) {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1997 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); 2035 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
1998 return Add<HLoadKeyed>( 2036 return Add<HLoadKeyed>(
1999 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 2037 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
2000 } 2038 }
2001 2039
2002 2040
2003 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, 2041 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
2004 ElementsKind kind, 2042 ElementsKind kind,
2005 HValue* allocation_site_payload, 2043 HValue* allocation_site_payload,
2006 HValue* constructor_function, 2044 HValue* constructor_function,
2007 AllocationSiteOverrideMode override_mode) : 2045 AllocationSiteOverrideMode override_mode,
2046 bool is_inlined) :
2008 builder_(builder), 2047 builder_(builder),
2009 kind_(kind), 2048 kind_(kind),
2010 allocation_site_payload_(allocation_site_payload), 2049 allocation_site_payload_(allocation_site_payload),
2011 constructor_function_(constructor_function) { 2050 constructor_function_(constructor_function),
2051 is_inlined_(is_inlined) {
2012 mode_ = override_mode == DISABLE_ALLOCATION_SITES 2052 mode_ = override_mode == DISABLE_ALLOCATION_SITES
2013 ? DONT_TRACK_ALLOCATION_SITE 2053 ? DONT_TRACK_ALLOCATION_SITE
2014 : AllocationSite::GetMode(kind); 2054 : AllocationSite::GetMode(kind);
2015 } 2055 }
2016 2056
2017 2057
2018 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, 2058 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
2019 ElementsKind kind, 2059 ElementsKind kind,
2020 HValue* constructor_function) : 2060 HValue* constructor_function) :
2021 builder_(builder), 2061 builder_(builder),
2022 kind_(kind), 2062 kind_(kind),
2023 mode_(DONT_TRACK_ALLOCATION_SITE), 2063 mode_(DONT_TRACK_ALLOCATION_SITE),
2024 allocation_site_payload_(NULL), 2064 allocation_site_payload_(NULL),
2025 constructor_function_(constructor_function) { 2065 constructor_function_(constructor_function),
2066 is_inlined_(false) {
2026 } 2067 }
2027 2068
2028 2069
2029 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { 2070 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
2071 if (is_inlined_) {
Toon Verwaest 2013/11/11 13:59:28 Is it good enough to use IsStub() rather than is_i
mvstanton 2013/11/13 14:12:52 Sure is, thanks for the idea. Done.
2072 // A constant map is fine.
2073 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
2074 builder()->isolate());
2075 return builder()->Add<HConstant>(map);
2076 }
2077
2030 if (kind_ == GetInitialFastElementsKind()) { 2078 if (kind_ == GetInitialFastElementsKind()) {
2031 // No need for a context lookup if the kind_ matches the initial 2079 // No need for a context lookup if the kind_ matches the initial
2032 // map, because we can just load the map in that case. 2080 // map, because we can just load the map in that case.
2033 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2081 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2034 return builder()->AddLoadNamedField(constructor_function_, access); 2082 return builder()->AddLoadNamedField(constructor_function_, access);
2035 } 2083 }
2036 2084
2037 HInstruction* native_context = builder()->BuildGetNativeContext(); 2085 HInstruction* native_context = builder()->BuildGetNativeContext();
2038 HInstruction* index = builder()->Add<HConstant>( 2086 HInstruction* index = builder()->Add<HConstant>(
2039 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 2087 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
(...skipping 20 matching lines...) Expand all
2060 ASSERT(length_node != NULL); 2108 ASSERT(length_node != NULL);
2061 2109
2062 int base_size = JSArray::kSize; 2110 int base_size = JSArray::kSize;
2063 if (mode_ == TRACK_ALLOCATION_SITE) { 2111 if (mode_ == TRACK_ALLOCATION_SITE) {
2064 base_size += AllocationMemento::kSize; 2112 base_size += AllocationMemento::kSize;
2065 } 2113 }
2066 2114
2067 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); 2115 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
2068 base_size += FixedArray::kHeaderSize; 2116 base_size += FixedArray::kHeaderSize;
2069 2117
2118 if (length_node->IsConstant()) {
2119 HConstant* constant_length_node = HConstant::cast(length_node);
2120 if (constant_length_node->HasInteger32Value()) {
2121 int size = base_size + elements_size() *
2122 constant_length_node->Integer32Value();
2123 HInstruction* const_size = builder()->Add<HConstant>(size);
2124 return const_size;
Toon Verwaest 2013/11/11 13:59:28 I think constant folding should take care of this.
mvstanton 2013/11/13 14:12:52 Indeed, thx!
2125 }
2126 }
2127
2070 HInstruction* elements_size_value = 2128 HInstruction* elements_size_value =
2071 builder()->Add<HConstant>(elements_size()); 2129 builder()->Add<HConstant>(elements_size());
2072 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value); 2130 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value);
2073 mul->ClearFlag(HValue::kCanOverflow); 2131 mul->ClearFlag(HValue::kCanOverflow);
2074 2132
2075 HInstruction* base = builder()->Add<HConstant>(base_size); 2133 HInstruction* base = builder()->Add<HConstant>(base_size);
2076 HInstruction* total_size = builder()->Add<HAdd>(base, mul); 2134 HInstruction* total_size = builder()->Add<HAdd>(base, mul);
2077 total_size->ClearFlag(HValue::kCanOverflow); 2135 total_size->ClearFlag(HValue::kCanOverflow);
2078 return total_size; 2136 return total_size;
2079 } 2137 }
(...skipping 11 matching lines...) Expand all
2091 2149
2092 return builder()->Add<HConstant>(base_size); 2150 return builder()->Add<HConstant>(base_size);
2093 } 2151 }
2094 2152
2095 2153
2096 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { 2154 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
2097 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); 2155 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize();
2098 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); 2156 HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
2099 return AllocateArray(size_in_bytes, 2157 return AllocateArray(size_in_bytes,
2100 capacity, 2158 capacity,
2101 builder()->graph()->GetConstant0(), 2159 builder()->graph()->GetConstant0());
2102 true);
2103 } 2160 }
2104 2161
2105 2162
2106 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, 2163 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity,
2107 HValue* length_field, 2164 HValue* length_field,
2108 bool fill_with_hole) { 2165 FillMode fill_mode) {
2109 HValue* size_in_bytes = EstablishAllocationSize(capacity); 2166 HValue* size_in_bytes = EstablishAllocationSize(capacity);
2110 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); 2167 return AllocateArray(size_in_bytes, capacity, length_field, fill_mode);
2111 } 2168 }
2112 2169
2113 2170
2114 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, 2171 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
2115 HValue* capacity, 2172 HValue* capacity,
2116 HValue* length_field, 2173 HValue* length_field,
2117 bool fill_with_hole) { 2174 FillMode fill_mode) {
2118 // These HForceRepresentations are because we store these as fields in the 2175 // These HForceRepresentations are because we store these as fields in the
2119 // objects we construct, and an int32-to-smi HChange could deopt. Accept 2176 // objects we construct, and an int32-to-smi HChange could deopt. Accept
2120 // the deopt possibility now, before allocation occurs. 2177 // the deopt possibility now, before allocation occurs.
2121 capacity = builder()->Add<HForceRepresentation>(capacity, 2178 capacity = builder()->Add<HForceRepresentation>(capacity,
2122 Representation::Smi()); 2179 Representation::Smi());
2123 length_field = builder()->Add<HForceRepresentation>(length_field, 2180 length_field = builder()->Add<HForceRepresentation>(length_field,
2124 Representation::Smi()); 2181 Representation::Smi());
2125 // Allocate (dealing with failure appropriately) 2182 // Allocate (dealing with failure appropriately)
2126 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, 2183 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes,
2127 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); 2184 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE);
(...skipping 13 matching lines...) Expand all
2141 elements_location_ = builder()->BuildJSArrayHeader(new_object, 2198 elements_location_ = builder()->BuildJSArrayHeader(new_object,
2142 map, 2199 map,
2143 mode_, 2200 mode_,
2144 kind_, 2201 kind_,
2145 allocation_site_payload_, 2202 allocation_site_payload_,
2146 length_field); 2203 length_field);
2147 2204
2148 // Initialize the elements 2205 // Initialize the elements
2149 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); 2206 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
2150 2207
2151 if (fill_with_hole) { 2208 if (fill_mode == FILL_WITH_HOLE) {
2152 builder()->BuildFillElementsWithHole(elements_location_, kind_, 2209 builder()->BuildFillElementsWithHole(elements_location_, kind_,
2153 graph()->GetConstant0(), capacity); 2210 graph()->GetConstant0(), capacity);
2154 } 2211 }
2155 2212
2156 return new_object; 2213 return new_object;
2157 } 2214 }
2158 2215
2159 2216
2160 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, 2217 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
2161 Handle<Map> map) { 2218 Handle<Map> map) {
(...skipping 5000 matching lines...) Expand 10 before | Expand all | Expand 10 after
7162 7219
7163 call = New<HCallFunction>(function, argument_count); 7220 call = New<HCallFunction>(function, argument_count);
7164 Drop(argument_count + 1); 7221 Drop(argument_count + 1);
7165 } 7222 }
7166 } 7223 }
7167 7224
7168 return ast_context()->ReturnInstruction(call, expr->id()); 7225 return ast_context()->ReturnInstruction(call, expr->id());
7169 } 7226 }
7170 7227
7171 7228
7229 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) {
7230 NoObservableSideEffectsScope no_effects(this);
7231
7232 int argument_count = expr->arguments()->length();
7233 // We should at least have the constructor on the expression stack.
7234 ASSERT(!environment()->ExpressionStackIsEmpty());
Toon Verwaest 2013/11/11 13:59:28 I this ASSERT and the comment necessary? Doesn't t
mvstanton 2013/11/13 14:12:52 Done.
7235 HValue* constructor = environment()->ExpressionStackAt(argument_count);
7236
7237 ElementsKind kind = expr->elements_kind();
7238 Handle<Cell> cell = expr->allocation_info_cell();
7239 AllocationSite* site = AllocationSite::cast(cell->value());
7240
7241 // Register on the site for deoptimization if the cell value changes.
7242 site->AddDependentCompilationInfo(AllocationSite::TRANSITIONS, top_info());
7243 HInstruction* cell_instruction = Add<HConstant>(cell);
7244
7245 // In the single constant argument case, we may have to adjust elements kind
7246 // to avoid creating a packed non-empty array (not kosher).
Toon Verwaest 2013/11/11 13:59:28 I'd remove the (not kosher) part.
mvstanton 2013/11/13 14:12:52 Done.
7247 if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
Toon Verwaest 2013/11/11 13:59:28 Can't we just do this in BuildAllocateArrayFromLen
mvstanton 2013/11/13 14:12:52 Hmm, I'd rather not because then the JSArrayBuilde
7248 HValue* argument = environment()->Top();
7249 if (argument->IsConstant()) {
7250 HConstant* constant_argument = HConstant::cast(argument);
7251 ASSERT(constant_argument->HasSmiValue());
7252 int constant_array_size = constant_argument->Integer32Value();
7253 if (constant_array_size != 0) {
7254 kind = GetHoleyElementsKind(kind);
7255 }
7256 }
7257 }
7258
7259 // Build the array.
7260 JSArrayBuilder array_builder(this,
7261 kind,
7262 cell_instruction,
7263 constructor,
7264 DISABLE_ALLOCATION_SITES,
7265 true);
7266 HValue* new_object;
7267 if (argument_count == 0) {
7268 new_object = array_builder.AllocateEmptyArray();
7269 } else if (argument_count == 1) {
7270 HValue* argument = environment()->Top();
7271 new_object = BuildAllocateArrayFromLength(&array_builder, argument);
7272 } else {
7273 HValue* length = Add<HConstant>(argument_count);
7274 // Smi arrays need to initialize array elements with the hole because
7275 // bailout could occur if the arguments don't fit in a smi.
7276 //
7277 // TODO(mvstanton): If all the arguments are constants in smi range, then
7278 // we could set fill_with_hole to false and save a few instructions.
7279 JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind)
7280 ? JSArrayBuilder::FILL_WITH_HOLE
7281 : JSArrayBuilder::DONT_FILL_WITH_HOLE;
7282 new_object = array_builder.AllocateArray(length, length, fill_mode);
7283 HValue* elements = array_builder.GetElementsLocation();
7284 for (int i = 0; i < argument_count; i++) {
7285 HValue* value = environment()->ExpressionStackAt(argument_count - i - 1);
7286 HValue* constant_i = Add<HConstant>(i);
7287 Add<HStoreKeyed>(elements, constant_i, value, kind);
7288 }
7289 }
7290
7291 Drop(argument_count + 1); // drop constructor and args.
7292 ast_context()->ReturnValue(new_object);
7293 }
7294
7295
7172 // Checks whether allocation using the given constructor can be inlined. 7296 // Checks whether allocation using the given constructor can be inlined.
7173 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { 7297 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
7174 return constructor->has_initial_map() && 7298 return constructor->has_initial_map() &&
7175 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && 7299 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
7176 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && 7300 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
7177 constructor->initial_map()->InitialPropertiesLength() == 0; 7301 constructor->initial_map()->InitialPropertiesLength() == 0;
7178 } 7302 }
7179 7303
7180 7304
7305 bool HOptimizedGraphBuilder::IsCallNewArrayInlineable(CallNew* expr) {
7306 bool inline_ok = false;
7307 Handle<JSFunction> caller = current_info()->closure();
7308 Handle<JSFunction> target(isolate()->global_context()->array_function(),
7309 isolate());
7310 int argument_count = expr->arguments()->length();
7311 // We should have the function plus array arguments on the environment stack.
7312 ASSERT(environment()->length() >= (argument_count + 1));
7313 Handle<Cell> cell = expr->allocation_info_cell();
7314 AllocationSite* site = AllocationSite::cast(cell->value());
7315 if (site->CanInlineCall()) {
7316 // We also want to avoid inlining in certain 1 argument scenarios.
7317 if (argument_count == 1) {
7318 HValue* argument = Top();
7319 if (argument->IsConstant()) {
7320 // Do not inline if the constant length argument is not a smi or
7321 // outside the valid range for a fast array.
7322 HConstant* constant_argument = HConstant::cast(argument);
7323 if (constant_argument->HasSmiValue()) {
7324 int value = constant_argument->Integer32Value();
7325 inline_ok = value >= 0 &&
7326 value < JSObject::kInitialMaxFastElementArray;
7327 if (!inline_ok) {
7328 TraceInline(target, caller,
7329 "Length outside of valid array range");
7330 }
7331 }
7332 } else {
7333 // The amount of code we'd have to generate doubles if we have a
7334 // non-constant length, but packed elements_kind feedback. Don't
7335 // inline this case.
7336 inline_ok = IsHoleyElementsKind(expr->elements_kind());
Toon Verwaest 2013/11/11 13:59:28 Shouldn't we just deopt if the passed length is no
mvstanton 2013/11/13 14:12:52 Yep, done. I also added a test in array-constructo
7337 if (!inline_ok) {
7338 TraceInline(target, caller,
7339 "Non-holey elements kind for single argument");
7340 }
7341 }
7342 } else {
7343 inline_ok = true;
7344 }
7345 } else {
7346 TraceInline(target, caller, "AllocationSite requested no inlining.");
7347 }
7348
7349 if (inline_ok) {
7350 TraceInline(target, caller, NULL);
7351 }
7352 return inline_ok;
7353 }
7354
7355
7181 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 7356 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
7182 ASSERT(!HasStackOverflow()); 7357 ASSERT(!HasStackOverflow());
7183 ASSERT(current_block() != NULL); 7358 ASSERT(current_block() != NULL);
7184 ASSERT(current_block()->HasPredecessor()); 7359 ASSERT(current_block()->HasPredecessor());
7185 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 7360 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
7186 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 7361 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
7187 Factory* factory = isolate()->factory(); 7362 Factory* factory = isolate()->factory();
7188 7363
7364 // The constructor function is on the stack in the unoptimized code
7365 // during evaluation of the arguments.
7366 CHECK_ALIVE(VisitForValue(expr->expression()));
7367 HValue* function = Top();
7368 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7369
7189 if (FLAG_inline_construct && 7370 if (FLAG_inline_construct &&
7190 expr->IsMonomorphic() && 7371 expr->IsMonomorphic() &&
7191 IsAllocationInlineable(expr->target())) { 7372 IsAllocationInlineable(expr->target())) {
7192 // The constructor function is on the stack in the unoptimized code
7193 // during evaluation of the arguments.
7194 CHECK_ALIVE(VisitForValue(expr->expression()));
7195 HValue* function = Top();
7196 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7197 Handle<JSFunction> constructor = expr->target(); 7373 Handle<JSFunction> constructor = expr->target();
7198 HValue* check = Add<HCheckValue>(function, constructor); 7374 HValue* check = Add<HCheckValue>(function, constructor);
7199 7375
7200 // Force completion of inobject slack tracking before generating 7376 // Force completion of inobject slack tracking before generating
7201 // allocation code to finalize instance size. 7377 // allocation code to finalize instance size.
7202 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { 7378 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
7203 constructor->shared()->CompleteInobjectSlackTracking(); 7379 constructor->shared()->CompleteInobjectSlackTracking();
7204 } 7380 }
7205 7381
7206 // Calculate instance size from initial map of constructor. 7382 // Calculate instance size from initial map of constructor.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
7273 check->DeleteAndReplaceWith(NULL); 7449 check->DeleteAndReplaceWith(NULL);
7274 environment()->SetExpressionStackAt(receiver_index, function); 7450 environment()->SetExpressionStackAt(receiver_index, function);
7275 HInstruction* call = 7451 HInstruction* call =
7276 PreProcessCall(New<HCallNew>(function, argument_count)); 7452 PreProcessCall(New<HCallNew>(function, argument_count));
7277 return ast_context()->ReturnInstruction(call, expr->id()); 7453 return ast_context()->ReturnInstruction(call, expr->id());
7278 } else { 7454 } else {
7279 // The constructor function is both an operand to the instruction and an 7455 // The constructor function is both an operand to the instruction and an
7280 // argument to the construct call. 7456 // argument to the construct call.
7281 Handle<JSFunction> array_function( 7457 Handle<JSFunction> array_function(
7282 isolate()->global_context()->array_function(), isolate()); 7458 isolate()->global_context()->array_function(), isolate());
7283 CHECK_ALIVE(VisitArgument(expr->expression())); 7459 bool use_call_new_array = expr->target().is_identical_to(array_function);
7284 HValue* constructor = HPushArgument::cast(Top())->argument(); 7460 Handle<Cell> cell = expr->allocation_info_cell();
7285 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7461 if (use_call_new_array && IsCallNewArrayInlineable(expr)) {
7462 // Verify we are still calling the array function for our native context.
7463 Add<HCheckValue>(function, array_function);
7464 BuildInlinedCallNewArray(expr);
7465 return;
7466 }
7467
7286 HBinaryCall* call; 7468 HBinaryCall* call;
7287 if (expr->target().is_identical_to(array_function)) { 7469 if (use_call_new_array) {
7288 Handle<Cell> cell = expr->allocation_info_cell(); 7470 Add<HCheckValue>(function, array_function);
7289 Add<HCheckValue>(constructor, array_function); 7471 call = New<HCallNewArray>(function, argument_count, cell,
7290 call = New<HCallNewArray>(constructor, argument_count, 7472 expr->elements_kind());
7291 cell, expr->elements_kind());
7292 } else { 7473 } else {
7293 call = New<HCallNew>(constructor, argument_count); 7474 call = New<HCallNew>(function, argument_count);
7294 } 7475 }
7295 Drop(argument_count); 7476 PreProcessCall(call);
7296 return ast_context()->ReturnInstruction(call, expr->id()); 7477 return ast_context()->ReturnInstruction(call, expr->id());
7297 } 7478 }
7298 } 7479 }
7299 7480
7300 7481
7301 // Support for generating inlined runtime functions. 7482 // Support for generating inlined runtime functions.
7302 7483
7303 // Lookup table for generators for runtime calls that are generated inline. 7484 // Lookup table for generators for runtime calls that are generated inline.
7304 // Elements of the table are member pointers to functions of 7485 // Elements of the table are member pointers to functions of
7305 // HOptimizedGraphBuilder. 7486 // HOptimizedGraphBuilder.
(...skipping 2517 matching lines...) Expand 10 before | Expand all | Expand 10 after
9823 if (ShouldProduceTraceOutput()) { 10004 if (ShouldProduceTraceOutput()) {
9824 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10005 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9825 } 10006 }
9826 10007
9827 #ifdef DEBUG 10008 #ifdef DEBUG
9828 graph_->Verify(false); // No full verify. 10009 graph_->Verify(false); // No full verify.
9829 #endif 10010 #endif
9830 } 10011 }
9831 10012
9832 } } // namespace v8::internal 10013 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698