OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { | 1270 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
1271 Handle<JSFunction> f = Handle<JSFunction>::cast( | 1271 Handle<JSFunction> f = Handle<JSFunction>::cast( |
1272 HConstant::cast(function)->handle(isolate())); | 1272 HConstant::cast(function)->handle(isolate())); |
1273 SharedFunctionInfo* shared = f->shared(); | 1273 SharedFunctionInfo* shared = f->shared(); |
1274 if (shared->strict_mode() == STRICT || shared->native()) return object; | 1274 if (shared->strict_mode() == STRICT || shared->native()) return object; |
1275 } | 1275 } |
1276 return Add<HWrapReceiver>(object, function); | 1276 return Add<HWrapReceiver>(object, function); |
1277 } | 1277 } |
1278 | 1278 |
1279 | 1279 |
| 1280 HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(HValue* object, |
| 1281 HValue* elements, |
| 1282 ElementsKind kind, |
| 1283 HValue* length, |
| 1284 HValue* capacity, |
| 1285 HValue* key) { |
| 1286 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); |
| 1287 HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap); |
| 1288 Add<HBoundsCheck>(key, max_capacity); |
| 1289 |
| 1290 HValue* new_capacity = BuildNewElementsCapacity(key); |
| 1291 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
| 1292 kind, kind, length, |
| 1293 new_capacity); |
| 1294 return new_elements; |
| 1295 } |
| 1296 |
| 1297 |
1280 HValue* HGraphBuilder::BuildCheckForCapacityGrow( | 1298 HValue* HGraphBuilder::BuildCheckForCapacityGrow( |
1281 HValue* object, | 1299 HValue* object, |
1282 HValue* elements, | 1300 HValue* elements, |
1283 ElementsKind kind, | 1301 ElementsKind kind, |
1284 HValue* length, | 1302 HValue* length, |
1285 HValue* key, | 1303 HValue* key, |
1286 bool is_js_array, | 1304 bool is_js_array, |
1287 PropertyAccessType access_type) { | 1305 PropertyAccessType access_type) { |
1288 IfBuilder length_checker(this); | 1306 IfBuilder length_checker(this); |
1289 | 1307 |
1290 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; | 1308 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; |
1291 length_checker.If<HCompareNumericAndBranch>(key, length, token); | 1309 length_checker.If<HCompareNumericAndBranch>(key, length, token); |
1292 | 1310 |
1293 length_checker.Then(); | 1311 length_checker.Then(); |
1294 | 1312 |
1295 HValue* current_capacity = AddLoadFixedArrayLength(elements); | 1313 HValue* current_capacity = AddLoadFixedArrayLength(elements); |
1296 | 1314 |
1297 IfBuilder capacity_checker(this); | 1315 IfBuilder capacity_checker(this); |
1298 | 1316 |
1299 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, | 1317 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, |
1300 Token::GTE); | 1318 Token::GTE); |
1301 capacity_checker.Then(); | 1319 capacity_checker.Then(); |
1302 | 1320 |
1303 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); | 1321 // BuildCheckAndGrowElementsCapacity could de-opt without profitable feedback, |
1304 HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap); | 1322 // therefore we defer calling it to a stub in optimized functions. It is |
| 1323 // okay to call directly in a code stub though, because a bailout to the |
| 1324 // runtime is tolerable in the corner cases. |
| 1325 if (top_info()->IsStub()) { |
| 1326 environment()->Push( |
| 1327 BuildCheckAndGrowElementsCapacity(object, elements, kind, length, |
| 1328 current_capacity, key)); |
| 1329 } else { |
| 1330 GrowArrayElementsStub stub(isolate(), is_js_array, kind); |
| 1331 CodeStubInterfaceDescriptor* descriptor = |
| 1332 isolate()->code_stub_interface_descriptor(CodeStub::GrowArrayElements); |
| 1333 HConstant* target = Add<HConstant>(stub.GetCode()); |
| 1334 HValue* op_vals[] = { object, key, current_capacity }; |
| 1335 HValue* new_elements = Add<HCallWithDescriptor>( |
| 1336 target, 0, descriptor, Vector<HValue*>(op_vals, 3)); |
| 1337 // If the object changed to a dictionary, GrowArrayElements will return a |
| 1338 // smi to signal that deopt is required. |
| 1339 Add<HCheckHeapObject>(new_elements); |
| 1340 environment()->Push(new_elements); |
| 1341 } |
1305 | 1342 |
1306 Add<HBoundsCheck>(key, max_capacity); | |
1307 | |
1308 HValue* new_capacity = BuildNewElementsCapacity(key); | |
1309 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | |
1310 kind, kind, length, | |
1311 new_capacity); | |
1312 | |
1313 environment()->Push(new_elements); | |
1314 capacity_checker.Else(); | 1343 capacity_checker.Else(); |
1315 | |
1316 environment()->Push(elements); | 1344 environment()->Push(elements); |
1317 capacity_checker.End(); | 1345 capacity_checker.End(); |
1318 | 1346 |
1319 if (is_js_array) { | 1347 if (is_js_array) { |
1320 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); | 1348 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); |
1321 new_length->ClearFlag(HValue::kCanOverflow); | 1349 new_length->ClearFlag(HValue::kCanOverflow); |
1322 | 1350 |
1323 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), | 1351 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), |
1324 new_length); | 1352 new_length); |
1325 } | 1353 } |
(...skipping 1350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2676 | 2704 |
2677 | 2705 |
2678 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 2706 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
2679 HValue* elements, | 2707 HValue* elements, |
2680 ElementsKind kind, | 2708 ElementsKind kind, |
2681 ElementsKind new_kind, | 2709 ElementsKind new_kind, |
2682 HValue* length, | 2710 HValue* length, |
2683 HValue* new_capacity) { | 2711 HValue* new_capacity) { |
2684 Add<HBoundsCheck>(new_capacity, Add<HConstant>( | 2712 Add<HBoundsCheck>(new_capacity, Add<HConstant>( |
2685 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> | 2713 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> |
2686 ElementsKindToShiftSize(kind))); | 2714 ElementsKindToShiftSize(new_kind))); |
2687 | 2715 |
2688 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 2716 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
2689 new_kind, new_capacity); | 2717 new_kind, new_capacity); |
2690 | 2718 |
2691 BuildCopyElements(elements, kind, new_elements, | 2719 BuildCopyElements(elements, kind, new_elements, |
2692 new_kind, length, new_capacity); | 2720 new_kind, length, new_capacity); |
2693 | 2721 |
2694 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2722 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
2695 new_elements); | 2723 new_elements); |
2696 | 2724 |
(...skipping 9678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12375 if (ShouldProduceTraceOutput()) { | 12403 if (ShouldProduceTraceOutput()) { |
12376 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12404 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12377 } | 12405 } |
12378 | 12406 |
12379 #ifdef DEBUG | 12407 #ifdef DEBUG |
12380 graph_->Verify(false); // No full verify. | 12408 graph_->Verify(false); // No full verify. |
12381 #endif | 12409 #endif |
12382 } | 12410 } |
12383 | 12411 |
12384 } } // namespace v8::internal | 12412 } } // namespace v8::internal |
OLD | NEW |