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 4239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4250 __ PushReturnAddressFrom(rcx); | 4250 __ PushReturnAddressFrom(rcx); |
4251 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); | 4251 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); |
4252 | 4252 |
4253 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 4253 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
4254 // tagged as a small integer. | 4254 // tagged as a small integer. |
4255 __ bind(&runtime); | 4255 __ bind(&runtime); |
4256 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4256 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
4257 } | 4257 } |
4258 | 4258 |
4259 | 4259 |
| 4260 void ArrayPushStub::Generate(MacroAssembler* masm) { |
| 4261 int argc = arguments_count(); |
| 4262 |
| 4263 StackArgumentsAccessor args(rsp, argc); |
| 4264 if (argc == 0) { |
| 4265 // Noop, return the length. |
| 4266 __ movp(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
| 4267 __ ret((argc + 1) * kPointerSize); |
| 4268 return; |
| 4269 } |
| 4270 |
| 4271 Isolate* isolate = masm->isolate(); |
| 4272 |
| 4273 if (argc != 1) { |
| 4274 __ TailCallExternalReference( |
| 4275 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |
| 4276 return; |
| 4277 } |
| 4278 |
| 4279 Label call_builtin, attempt_to_grow_elements, with_write_barrier; |
| 4280 |
| 4281 // Get the elements array of the object. |
| 4282 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 4283 |
| 4284 if (IsFastSmiOrObjectElementsKind(elements_kind())) { |
| 4285 // Check that the elements are in fast mode and writable. |
| 4286 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset), |
| 4287 isolate->factory()->fixed_array_map()); |
| 4288 __ j(not_equal, &call_builtin); |
| 4289 } |
| 4290 |
| 4291 // Get the array's length into rax and calculate new length. |
| 4292 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
| 4293 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); |
| 4294 __ addl(rax, Immediate(argc)); |
| 4295 |
| 4296 // Get the elements' length into rcx. |
| 4297 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |
| 4298 |
| 4299 // Check if we could survive without allocation. |
| 4300 __ cmpl(rax, rcx); |
| 4301 |
| 4302 if (IsFastSmiOrObjectElementsKind(elements_kind())) { |
| 4303 __ j(greater, &attempt_to_grow_elements); |
| 4304 |
| 4305 // Check if value is a smi. |
| 4306 __ movp(rcx, args.GetArgumentOperand(1)); |
| 4307 __ JumpIfNotSmi(rcx, &with_write_barrier); |
| 4308 |
| 4309 // Store the value. |
| 4310 __ movp(FieldOperand(rdi, |
| 4311 rax, |
| 4312 times_pointer_size, |
| 4313 FixedArray::kHeaderSize - argc * kPointerSize), |
| 4314 rcx); |
| 4315 } else { |
| 4316 __ j(greater, &call_builtin); |
| 4317 |
| 4318 __ movp(rcx, args.GetArgumentOperand(1)); |
| 4319 __ StoreNumberToDoubleElements( |
| 4320 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize); |
| 4321 } |
| 4322 |
| 4323 // Save new length. |
| 4324 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
| 4325 |
| 4326 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
| 4327 __ ret((argc + 1) * kPointerSize); |
| 4328 |
| 4329 if (IsFastDoubleElementsKind(elements_kind())) { |
| 4330 __ bind(&call_builtin); |
| 4331 __ TailCallExternalReference( |
| 4332 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |
| 4333 return; |
| 4334 } |
| 4335 |
| 4336 __ bind(&with_write_barrier); |
| 4337 |
| 4338 if (IsFastSmiElementsKind(elements_kind())) { |
| 4339 if (FLAG_trace_elements_transitions) __ jmp(&call_builtin); |
| 4340 |
| 4341 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), |
| 4342 isolate->factory()->heap_number_map()); |
| 4343 __ j(equal, &call_builtin); |
| 4344 |
| 4345 ElementsKind target_kind = IsHoleyElementsKind(elements_kind()) |
| 4346 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; |
| 4347 __ movp(rbx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); |
| 4348 __ movp(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset)); |
| 4349 __ movp(rbx, ContextOperand(rbx, Context::JS_ARRAY_MAPS_INDEX)); |
| 4350 const int header_size = FixedArrayBase::kHeaderSize; |
| 4351 // Verify that the object can be transitioned in place. |
| 4352 const int origin_offset = header_size + elements_kind() * kPointerSize; |
| 4353 __ movp(rdi, FieldOperand(rbx, origin_offset)); |
| 4354 __ cmpq(rdi, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 4355 __ j(not_equal, &call_builtin); |
| 4356 |
| 4357 const int target_offset = header_size + target_kind * kPointerSize; |
| 4358 __ movp(rbx, FieldOperand(rbx, target_offset)); |
| 4359 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
| 4360 masm, DONT_TRACK_ALLOCATION_SITE, NULL); |
| 4361 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 4362 } |
| 4363 |
| 4364 // Save new length. |
| 4365 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
| 4366 |
| 4367 // Store the value. |
| 4368 __ lea(rdx, FieldOperand(rdi, |
| 4369 rax, times_pointer_size, |
| 4370 FixedArray::kHeaderSize - argc * kPointerSize)); |
| 4371 __ movp(Operand(rdx, 0), rcx); |
| 4372 |
| 4373 __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
| 4374 OMIT_SMI_CHECK); |
| 4375 |
| 4376 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
| 4377 __ ret((argc + 1) * kPointerSize); |
| 4378 |
| 4379 __ bind(&attempt_to_grow_elements); |
| 4380 if (!FLAG_inline_new) { |
| 4381 __ bind(&call_builtin); |
| 4382 __ TailCallExternalReference( |
| 4383 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |
| 4384 return; |
| 4385 } |
| 4386 |
| 4387 __ movp(rbx, args.GetArgumentOperand(1)); |
| 4388 // Growing elements that are SMI-only requires special handling in case the |
| 4389 // new element is non-Smi. For now, delegate to the builtin. |
| 4390 Label no_fast_elements_check; |
| 4391 __ JumpIfSmi(rbx, &no_fast_elements_check); |
| 4392 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 4393 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); |
| 4394 __ bind(&no_fast_elements_check); |
| 4395 |
| 4396 ExternalReference new_space_allocation_top = |
| 4397 ExternalReference::new_space_allocation_top_address(isolate); |
| 4398 ExternalReference new_space_allocation_limit = |
| 4399 ExternalReference::new_space_allocation_limit_address(isolate); |
| 4400 |
| 4401 const int kAllocationDelta = 4; |
| 4402 ASSERT(kAllocationDelta >= argc); |
| 4403 // Load top. |
| 4404 __ Load(rcx, new_space_allocation_top); |
| 4405 |
| 4406 // Check if it's the end of elements. |
| 4407 __ lea(rdx, FieldOperand(rdi, |
| 4408 rax, times_pointer_size, |
| 4409 FixedArray::kHeaderSize - argc * kPointerSize)); |
| 4410 __ cmpq(rdx, rcx); |
| 4411 __ j(not_equal, &call_builtin); |
| 4412 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize)); |
| 4413 Operand limit_operand = masm->ExternalOperand(new_space_allocation_limit); |
| 4414 __ cmpq(rcx, limit_operand); |
| 4415 __ j(above, &call_builtin); |
| 4416 |
| 4417 // We fit and could grow elements. |
| 4418 __ Store(new_space_allocation_top, rcx); |
| 4419 |
| 4420 // Push the argument... |
| 4421 __ movp(Operand(rdx, 0), rbx); |
| 4422 // ... and fill the rest with holes. |
| 4423 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
| 4424 for (int i = 1; i < kAllocationDelta; i++) { |
| 4425 __ movp(Operand(rdx, i * kPointerSize), kScratchRegister); |
| 4426 } |
| 4427 |
| 4428 if (IsFastObjectElementsKind(elements_kind())) { |
| 4429 // We know the elements array is in new space so we don't need the |
| 4430 // remembered set, but we just pushed a value onto it so we may have to tell |
| 4431 // the incremental marker to rescan the object that we just grew. We don't |
| 4432 // need to worry about the holes because they are in old space and already |
| 4433 // marked black. |
| 4434 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); |
| 4435 } |
| 4436 |
| 4437 // Restore receiver to rdx as finish sequence assumes it's here. |
| 4438 __ movp(rdx, args.GetReceiverOperand()); |
| 4439 |
| 4440 // Increment element's and array's sizes. |
| 4441 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), |
| 4442 Smi::FromInt(kAllocationDelta)); |
| 4443 |
| 4444 // Make new length a smi before returning it. |
| 4445 __ Integer32ToSmi(rax, rax); |
| 4446 __ movp(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
| 4447 |
| 4448 __ ret((argc + 1) * kPointerSize); |
| 4449 |
| 4450 __ bind(&call_builtin); |
| 4451 __ TailCallExternalReference( |
| 4452 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |
| 4453 } |
| 4454 |
| 4455 |
4260 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 4456 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
4261 // ----------- S t a t e ------------- | 4457 // ----------- S t a t e ------------- |
4262 // -- rdx : left | 4458 // -- rdx : left |
4263 // -- rax : right | 4459 // -- rax : right |
4264 // -- rsp[0] : return address | 4460 // -- rsp[0] : return address |
4265 // ----------------------------------- | 4461 // ----------------------------------- |
4266 Isolate* isolate = masm->isolate(); | 4462 Isolate* isolate = masm->isolate(); |
4267 | 4463 |
4268 // Load rcx with the allocation site. We stick an undefined dummy value here | 4464 // Load rcx with the allocation site. We stick an undefined dummy value here |
4269 // and replace it with the real allocation site later when we instantiate this | 4465 // and replace it with the real allocation site later when we instantiate this |
(...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5528 __ bind(&fast_elements_case); | 5724 __ bind(&fast_elements_case); |
5529 GenerateCase(masm, FAST_ELEMENTS); | 5725 GenerateCase(masm, FAST_ELEMENTS); |
5530 } | 5726 } |
5531 | 5727 |
5532 | 5728 |
5533 #undef __ | 5729 #undef __ |
5534 | 5730 |
5535 } } // namespace v8::internal | 5731 } } // namespace v8::internal |
5536 | 5732 |
5537 #endif // V8_TARGET_ARCH_X64 | 5733 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |