| 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 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 | 881 |
| 882 if (entry == NULL) { | 882 if (entry == NULL) { |
| 883 Abort("bailout was not prepared"); | 883 Abort("bailout was not prepared"); |
| 884 return; | 884 return; |
| 885 } | 885 } |
| 886 | 886 |
| 887 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on A64. | 887 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on A64. |
| 888 if (FLAG_deopt_every_n_times == 1 && | 888 if (FLAG_deopt_every_n_times == 1 && |
| 889 !info()->IsStub() && | 889 !info()->IsStub() && |
| 890 info()->opt_count() == id) { | 890 info()->opt_count() == id) { |
| 891 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); | 891 ASSERT(frame_is_built_); |
| 892 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 892 return; | 893 return; |
| 893 } | 894 } |
| 894 | 895 |
| 895 if (FLAG_trap_on_deopt && info()->IsOptimizing()) { | 896 if (FLAG_trap_on_deopt && info()->IsOptimizing()) { |
| 896 __ Debug("trap_on_deopt", __LINE__, BREAK); | 897 __ Debug("trap_on_deopt", __LINE__, BREAK); |
| 897 } | 898 } |
| 898 | 899 |
| 899 | 900 |
| 900 // TODO(all): Currently this code directly jump to the second level deopt | 901 // TODO(all): Currently this code directly jump to the second level deopt |
| 901 // table entry. This code need to be updated if we decide to use the | 902 // table entry. This code need to be updated if we decide to use the |
| 902 // 2 levels of table. | 903 // 2 levels of table. |
| 903 ASSERT(info()->IsStub() || frame_is_built_); | 904 ASSERT(info()->IsStub() || frame_is_built_); |
| 904 bool needs_lazy_deopt = info()->IsStub(); | |
| 905 if (frame_is_built_) { | 905 if (frame_is_built_) { |
| 906 if (needs_lazy_deopt) { | 906 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 907 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | |
| 908 } else { | |
| 909 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); | |
| 910 } | |
| 911 } else { | 907 } else { |
| 912 // We need to build a frame to deoptimize a stub. Because stubs don't have a | 908 // We need to build a frame to deoptimize a stub. Because stubs don't have a |
| 913 // function pointer to put in the frame, put a special marker there instead. | 909 // function pointer to put in the frame, put a special marker there instead. |
| 914 // TODO(jbramley): In other architectures, this happens in the jump table. | 910 // TODO(jbramley): In other architectures, this happens in the jump table. |
| 915 // This is a temporary hack until we implement jump tables in A64. | 911 // This is a temporary hack until we implement jump tables in A64. |
| 916 __ Mov(__ Tmp1(), Operand(Smi::FromInt(StackFrame::STUB))); | 912 __ Mov(__ Tmp1(), Operand(Smi::FromInt(StackFrame::STUB))); |
| 917 __ Push(lr, fp, cp, __ Tmp1()); | 913 __ Push(lr, fp, cp, __ Tmp1()); |
| 918 __ Add(fp, __ StackPointer(), 2 * kPointerSize); | 914 __ Add(fp, __ StackPointer(), 2 * kPointerSize); |
| 919 // TODO(jbramley): Can this be a jump, rather than a call? | 915 // TODO(jbramley): Can this be a jump, rather than a call? |
| 920 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 916 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); | 1339 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); |
| 1344 } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) { | 1340 } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) { |
| 1345 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); | 1341 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); |
| 1346 } else { | 1342 } else { |
| 1347 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); | 1343 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); |
| 1348 } | 1344 } |
| 1349 __ StoreToSafepointRegisterSlot(x0, result); | 1345 __ StoreToSafepointRegisterSlot(x0, result); |
| 1350 } | 1346 } |
| 1351 | 1347 |
| 1352 | 1348 |
| 1353 void LCodeGen::DoAllocateObject(LAllocateObject* instr) { | |
| 1354 class DeferredAllocateObject: public LDeferredCode { | |
| 1355 public: | |
| 1356 DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) | |
| 1357 : LDeferredCode(codegen), instr_(instr) { } | |
| 1358 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } | |
| 1359 virtual LInstruction* instr() { return instr_; } | |
| 1360 private: | |
| 1361 LAllocateObject* instr_; | |
| 1362 }; | |
| 1363 | |
| 1364 DeferredAllocateObject* deferred = | |
| 1365 new(zone()) DeferredAllocateObject(this, instr); | |
| 1366 | |
| 1367 Register result = ToRegister(instr->result()); | |
| 1368 Register scratch1 = ToRegister(instr->temp1()); | |
| 1369 Register scratch2 = ToRegister(instr->temp2()); | |
| 1370 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | |
| 1371 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map(); | |
| 1372 int instance_size = initial_map->instance_size(); | |
| 1373 | |
| 1374 ASSERT(initial_map->pre_allocated_property_fields() + | |
| 1375 initial_map->unused_property_fields() - | |
| 1376 initial_map->inobject_properties() == 0); | |
| 1377 | |
| 1378 __ Allocate(instance_size, result, scratch1, scratch2, deferred->entry(), | |
| 1379 TAG_OBJECT); | |
| 1380 | |
| 1381 __ Bind(deferred->exit()); | |
| 1382 if (FLAG_debug_code) { | |
| 1383 Label is_in_new_space; | |
| 1384 __ JumpIfInNewSpace(result, &is_in_new_space); | |
| 1385 __ Abort("Allocated object is not in new-space"); | |
| 1386 __ Bind(&is_in_new_space); | |
| 1387 } | |
| 1388 | |
| 1389 // Load the initial map. | |
| 1390 Register map = scratch1; | |
| 1391 __ LoadHeapObject(map, constructor); | |
| 1392 __ Ldr(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset)); | |
| 1393 | |
| 1394 // Initialize map and field of the newly allocated object. | |
| 1395 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | |
| 1396 __ Str(map, FieldMemOperand(result, JSObject::kMapOffset)); | |
| 1397 | |
| 1398 Register empty_array = scratch1; | |
| 1399 __ LoadRoot(empty_array, Heap::kEmptyFixedArrayRootIndex); | |
| 1400 __ Str(empty_array, FieldMemOperand(result, JSObject::kElementsOffset)); | |
| 1401 __ Str(empty_array, FieldMemOperand(result, JSObject::kPropertiesOffset)); | |
| 1402 | |
| 1403 if (initial_map->inobject_properties() != 0) { | |
| 1404 Register undef = scratch1; | |
| 1405 __ LoadRoot(undef, Heap::kUndefinedValueRootIndex); | |
| 1406 for (int i = 0; i < initial_map->inobject_properties(); i++) { | |
| 1407 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | |
| 1408 __ Str(undef, FieldMemOperand(result, property_offset)); | |
| 1409 } | |
| 1410 } | |
| 1411 } | |
| 1412 | |
| 1413 | |
| 1414 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { | |
| 1415 Register result = ToRegister(instr->result()); | |
| 1416 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map(); | |
| 1417 int instance_size = initial_map->instance_size(); | |
| 1418 | |
| 1419 | |
| 1420 // TODO(3095996): Get rid of this. For now, we need to make the | |
| 1421 // result register contain a valid pointer because it is already | |
| 1422 // contained in the register pointer map. | |
| 1423 __ Mov(result, 0); | |
| 1424 | |
| 1425 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | |
| 1426 __ Mov(x0, Operand(Smi::FromInt(instance_size))); | |
| 1427 __ Push(x0); | |
| 1428 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); | |
| 1429 __ StoreToSafepointRegisterSlot(x0, result); | |
| 1430 } | |
| 1431 | |
| 1432 | |
| 1433 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 1349 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 1434 Register receiver = ToRegister(instr->receiver()); | 1350 Register receiver = ToRegister(instr->receiver()); |
| 1435 Register function = ToRegister(instr->function()); | 1351 Register function = ToRegister(instr->function()); |
| 1436 Register length = ToRegister(instr->length()); | 1352 Register length = ToRegister(instr->length()); |
| 1437 Register elements = ToRegister(instr->elements()); | 1353 Register elements = ToRegister(instr->elements()); |
| 1438 Register scratch = x5; | 1354 Register scratch = x5; |
| 1439 ASSERT(receiver.Is(x0)); // Used for parameter count. | 1355 ASSERT(receiver.Is(x0)); // Used for parameter count. |
| 1440 ASSERT(function.Is(x1)); // Required by InvokeFunction. | 1356 ASSERT(function.Is(x1)); // Required by InvokeFunction. |
| 1441 ASSERT(ToRegister(instr->result()).Is(x0)); | 1357 ASSERT(ToRegister(instr->result()).Is(x0)); |
| 1442 ASSERT(instr->IsMarkedAsCall()); | 1358 ASSERT(instr->IsMarkedAsCall()); |
| (...skipping 4128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5571 __ Bind(&out_of_object); | 5487 __ Bind(&out_of_object); |
| 5572 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5488 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 5573 // Index is equal to negated out of object property index plus 1. | 5489 // Index is equal to negated out of object property index plus 1. |
| 5574 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5490 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 5575 __ Ldr(result, FieldMemOperand(result, | 5491 __ Ldr(result, FieldMemOperand(result, |
| 5576 FixedArray::kHeaderSize - kPointerSize)); | 5492 FixedArray::kHeaderSize - kPointerSize)); |
| 5577 __ Bind(&done); | 5493 __ Bind(&done); |
| 5578 } | 5494 } |
| 5579 | 5495 |
| 5580 } } // namespace v8::internal | 5496 } } // namespace v8::internal |
| OLD | NEW |