OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1324 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1324 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
1325 name, &miss); | 1325 name, &miss); |
1326 | 1326 |
1327 if (argc == 0) { | 1327 if (argc == 0) { |
1328 // Noop, return the length. | 1328 // Noop, return the length. |
1329 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1329 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
1330 __ ret((argc + 1) * kPointerSize); | 1330 __ ret((argc + 1) * kPointerSize); |
1331 } else { | 1331 } else { |
1332 Label call_builtin; | 1332 Label call_builtin; |
1333 | 1333 |
1334 // Get the elements array of the object. | |
1335 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | |
1336 | |
1337 // Check that the elements are in fast mode and writable. | |
1338 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | |
1339 factory()->fixed_array_map()); | |
1340 __ j(not_equal, &call_builtin); | |
1341 | |
1342 if (argc == 1) { // Otherwise fall through to call builtin. | 1334 if (argc == 1) { // Otherwise fall through to call builtin. |
1343 Label attempt_to_grow_elements, with_write_barrier; | 1335 Label attempt_to_grow_elements, with_write_barrier; |
1344 | 1336 |
1337 // Get the elements array of the object. | |
1338 __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset)); | |
1339 | |
1340 // Check that the elements are in fast mode and writable. | |
1341 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset), | |
1342 factory()->fixed_array_map()); | |
1343 __ j(not_equal, &call_builtin); | |
1344 | |
1345 // Get the array's length into rax and calculate new length. | 1345 // Get the array's length into rax and calculate new length. |
1346 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1346 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
1347 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); | 1347 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); |
1348 __ addl(rax, Immediate(argc)); | 1348 __ addl(rax, Immediate(argc)); |
1349 | 1349 |
1350 // Get the element's length into rcx. | 1350 // Get the element's length into rcx. |
1351 __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); | 1351 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |
1352 | 1352 |
1353 // Check if we could survive without allocation. | 1353 // Check if we could survive without allocation. |
1354 __ cmpl(rax, rcx); | 1354 __ cmpl(rax, rcx); |
1355 __ j(greater, &attempt_to_grow_elements); | 1355 __ j(greater, &attempt_to_grow_elements); |
1356 | 1356 |
1357 // Check if value is a smi. | 1357 // Check if value is a smi. |
1358 __ movq(rcx, Operand(rsp, argc * kPointerSize)); | 1358 __ movq(rcx, Operand(rsp, argc * kPointerSize)); |
1359 __ JumpIfNotSmi(rcx, &with_write_barrier); | 1359 __ JumpIfNotSmi(rcx, &with_write_barrier); |
1360 | 1360 |
1361 // Save new length. | 1361 // Save new length. |
1362 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1362 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
1363 | 1363 |
1364 // Push the element. | 1364 // Push the element. |
1365 __ lea(rdx, FieldOperand(rbx, | 1365 __ movq(FieldOperand(rdi, |
1366 rax, times_pointer_size, | 1366 rax, times_pointer_size, |
Jakob Kummerow
2012/02/08 16:24:55
nit: I'd align this under "rdi".
| |
1367 FixedArray::kHeaderSize - argc * kPointerSize)); | 1367 FixedArray::kHeaderSize - argc * kPointerSize), |
1368 __ movq(Operand(rdx, 0), rcx); | 1368 rcx); |
1369 | 1369 |
1370 __ Integer32ToSmi(rax, rax); // Return new length as smi. | 1370 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
1371 __ ret((argc + 1) * kPointerSize); | 1371 __ ret((argc + 1) * kPointerSize); |
1372 | 1372 |
1373 __ bind(&with_write_barrier); | 1373 __ bind(&with_write_barrier); |
1374 | 1374 |
1375 __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset)); | 1375 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
1376 __ CheckFastObjectElements(rdi, &call_builtin); | 1376 |
1377 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { | |
1378 Label fast_object, not_fast_object; | |
1379 __ CheckFastObjectElements(rbx, ¬_fast_object, Label::kNear); | |
1380 __ jmp(&fast_object); | |
1381 // In case of fast smi-only, convert to fast object, otherwise bail out. | |
1382 __ bind(¬_fast_object); | |
1383 __ CheckFastSmiOnlyElements(rbx, &call_builtin); | |
1384 // rdx: receiver | |
1385 // rbx: map | |
1386 __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, | |
1387 FAST_ELEMENTS, | |
1388 rbx, | |
1389 r10, | |
1390 &call_builtin); | |
1391 ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm()); | |
1392 __ bind(&fast_object); | |
1393 } else { | |
1394 __ CheckFastObjectElements(rbx, &call_builtin); | |
1395 } | |
1396 | |
1397 __ CheckFastObjectElements(rbx, &call_builtin); | |
1377 | 1398 |
1378 // Save new length. | 1399 // Save new length. |
1379 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1400 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
1380 | 1401 |
1381 // Push the element. | 1402 // Push the element. |
1382 __ lea(rdx, FieldOperand(rbx, | 1403 __ lea(rdx, FieldOperand(rdi, |
1383 rax, times_pointer_size, | 1404 rax, times_pointer_size, |
1384 FixedArray::kHeaderSize - argc * kPointerSize)); | 1405 FixedArray::kHeaderSize - argc * kPointerSize)); |
1385 __ movq(Operand(rdx, 0), rcx); | 1406 __ movq(Operand(rdx, 0), rcx); |
1386 | 1407 |
1387 __ RecordWrite(rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | 1408 __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
1388 OMIT_SMI_CHECK); | 1409 OMIT_SMI_CHECK); |
1389 | 1410 |
1390 __ Integer32ToSmi(rax, rax); // Return new length as smi. | 1411 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
1391 __ ret((argc + 1) * kPointerSize); | 1412 __ ret((argc + 1) * kPointerSize); |
1392 | 1413 |
1393 __ bind(&attempt_to_grow_elements); | 1414 __ bind(&attempt_to_grow_elements); |
1394 if (!FLAG_inline_new) { | 1415 if (!FLAG_inline_new) { |
1395 __ jmp(&call_builtin); | 1416 __ jmp(&call_builtin); |
1396 } | 1417 } |
1397 | 1418 |
1398 __ movq(rdi, Operand(rsp, argc * kPointerSize)); | 1419 __ movq(rbx, Operand(rsp, argc * kPointerSize)); |
1399 // Growing elements that are SMI-only requires special handling in case | 1420 // Growing elements that are SMI-only requires special handling in case |
1400 // the new element is non-Smi. For now, delegate to the builtin. | 1421 // the new element is non-Smi. For now, delegate to the builtin. |
1401 Label no_fast_elements_check; | 1422 Label no_fast_elements_check; |
1402 __ JumpIfSmi(rdi, &no_fast_elements_check); | 1423 __ JumpIfSmi(rbx, &no_fast_elements_check); |
1403 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 1424 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |
1404 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); | 1425 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); |
1405 __ bind(&no_fast_elements_check); | 1426 __ bind(&no_fast_elements_check); |
1406 | 1427 |
1407 ExternalReference new_space_allocation_top = | 1428 ExternalReference new_space_allocation_top = |
1408 ExternalReference::new_space_allocation_top_address(isolate()); | 1429 ExternalReference::new_space_allocation_top_address(isolate()); |
1409 ExternalReference new_space_allocation_limit = | 1430 ExternalReference new_space_allocation_limit = |
1410 ExternalReference::new_space_allocation_limit_address(isolate()); | 1431 ExternalReference::new_space_allocation_limit_address(isolate()); |
1411 | 1432 |
1412 const int kAllocationDelta = 4; | 1433 const int kAllocationDelta = 4; |
1413 // Load top. | 1434 // Load top. |
1414 __ Load(rcx, new_space_allocation_top); | 1435 __ Load(rcx, new_space_allocation_top); |
1415 | 1436 |
1416 // Check if it's the end of elements. | 1437 // Check if it's the end of elements. |
1417 __ lea(rdx, FieldOperand(rbx, | 1438 __ lea(rdx, FieldOperand(rdi, |
1418 rax, times_pointer_size, | 1439 rax, times_pointer_size, |
1419 FixedArray::kHeaderSize - argc * kPointerSize)); | 1440 FixedArray::kHeaderSize - argc * kPointerSize)); |
1420 __ cmpq(rdx, rcx); | 1441 __ cmpq(rdx, rcx); |
1421 __ j(not_equal, &call_builtin); | 1442 __ j(not_equal, &call_builtin); |
1422 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize)); | 1443 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize)); |
1423 Operand limit_operand = | 1444 Operand limit_operand = |
1424 masm()->ExternalOperand(new_space_allocation_limit); | 1445 masm()->ExternalOperand(new_space_allocation_limit); |
1425 __ cmpq(rcx, limit_operand); | 1446 __ cmpq(rcx, limit_operand); |
1426 __ j(above, &call_builtin); | 1447 __ j(above, &call_builtin); |
1427 | 1448 |
1428 // We fit and could grow elements. | 1449 // We fit and could grow elements. |
1429 __ Store(new_space_allocation_top, rcx); | 1450 __ Store(new_space_allocation_top, rcx); |
1430 | 1451 |
1431 // Push the argument... | 1452 // Push the argument... |
1432 __ movq(Operand(rdx, 0), rdi); | 1453 __ movq(Operand(rdx, 0), rbx); |
1433 // ... and fill the rest with holes. | 1454 // ... and fill the rest with holes. |
1434 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 1455 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
1435 for (int i = 1; i < kAllocationDelta; i++) { | 1456 for (int i = 1; i < kAllocationDelta; i++) { |
1436 __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); | 1457 __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); |
1437 } | 1458 } |
1438 | 1459 |
1439 // We know the elements array is in new space so we don't need the | 1460 // We know the elements array is in new space so we don't need the |
1440 // remembered set, but we just pushed a value onto it so we may have to | 1461 // remembered set, but we just pushed a value onto it so we may have to |
1441 // tell the incremental marker to rescan the object that we just grew. We | 1462 // tell the incremental marker to rescan the object that we just grew. We |
1442 // don't need to worry about the holes because they are in old space and | 1463 // don't need to worry about the holes because they are in old space and |
1443 // already marked black. | 1464 // already marked black. |
1444 __ RecordWrite(rbx, rdx, rdi, kDontSaveFPRegs, OMIT_REMEMBERED_SET); | 1465 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); |
1445 | 1466 |
1446 // Restore receiver to rdx as finish sequence assumes it's here. | 1467 // Restore receiver to rdx as finish sequence assumes it's here. |
1447 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1468 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
1448 | 1469 |
1449 // Increment element's and array's sizes. | 1470 // Increment element's and array's sizes. |
1450 __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset), | 1471 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), |
1451 Smi::FromInt(kAllocationDelta)); | 1472 Smi::FromInt(kAllocationDelta)); |
1452 | 1473 |
1453 // Make new length a smi before returning it. | 1474 // Make new length a smi before returning it. |
1454 __ Integer32ToSmi(rax, rax); | 1475 __ Integer32ToSmi(rax, rax); |
1455 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1476 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
1456 | 1477 |
1457 __ ret((argc + 1) * kPointerSize); | 1478 __ ret((argc + 1) * kPointerSize); |
1458 } | 1479 } |
1459 | 1480 |
1460 __ bind(&call_builtin); | 1481 __ bind(&call_builtin); |
(...skipping 2125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3586 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3607 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
3587 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 3608 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
3588 } | 3609 } |
3589 | 3610 |
3590 | 3611 |
3591 #undef __ | 3612 #undef __ |
3592 | 3613 |
3593 } } // namespace v8::internal | 3614 } } // namespace v8::internal |
3594 | 3615 |
3595 #endif // V8_TARGET_ARCH_X64 | 3616 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |