| 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 21 matching lines...) Expand all Loading... |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
| 34 #include "regexp-macro-assembler.h" | 34 #include "regexp-macro-assembler.h" |
| 35 #include "stub-cache.h" | 35 #include "stub-cache.h" |
| 36 #include "runtime.h" | 36 #include "runtime.h" |
| 37 | 37 |
| 38 namespace v8 { | 38 namespace v8 { |
| 39 namespace internal { | 39 namespace internal { |
| 40 | 40 |
| 41 | 41 |
| 42 void FastNewClosureStub::InitializeInterfaceDescriptor( |
| 43 Isolate* isolate, |
| 44 CodeStubInterfaceDescriptor* descriptor) { |
| 45 static Register registers[] = { rbx }; |
| 46 descriptor->register_param_count_ = 1; |
| 47 descriptor->register_params_ = registers; |
| 48 descriptor->deoptimization_handler_ = |
| 49 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry; |
| 50 } |
| 51 |
| 52 |
| 42 void ToNumberStub::InitializeInterfaceDescriptor( | 53 void ToNumberStub::InitializeInterfaceDescriptor( |
| 43 Isolate* isolate, | 54 Isolate* isolate, |
| 44 CodeStubInterfaceDescriptor* descriptor) { | 55 CodeStubInterfaceDescriptor* descriptor) { |
| 45 static Register registers[] = { rax }; | 56 static Register registers[] = { rax }; |
| 46 descriptor->register_param_count_ = 1; | 57 descriptor->register_param_count_ = 1; |
| 47 descriptor->register_params_ = registers; | 58 descriptor->register_params_ = registers; |
| 48 descriptor->deoptimization_handler_ = NULL; | 59 descriptor->deoptimization_handler_ = NULL; |
| 49 } | 60 } |
| 50 | 61 |
| 51 | 62 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 __ push(descriptor->register_params_[i]); | 299 __ push(descriptor->register_params_[i]); |
| 289 } | 300 } |
| 290 ExternalReference miss = descriptor->miss_handler(); | 301 ExternalReference miss = descriptor->miss_handler(); |
| 291 __ CallExternalReference(miss, descriptor->register_param_count_); | 302 __ CallExternalReference(miss, descriptor->register_param_count_); |
| 292 } | 303 } |
| 293 | 304 |
| 294 __ Ret(); | 305 __ Ret(); |
| 295 } | 306 } |
| 296 | 307 |
| 297 | 308 |
| 298 void FastNewClosureStub::Generate(MacroAssembler* masm) { | |
| 299 // Create a new closure from the given function info in new | |
| 300 // space. Set the context to the current context in rsi. | |
| 301 Counters* counters = masm->isolate()->counters(); | |
| 302 | |
| 303 Label gc; | |
| 304 __ Allocate(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT); | |
| 305 | |
| 306 __ IncrementCounter(counters->fast_new_closure_total(), 1); | |
| 307 | |
| 308 // Get the function info from the stack. | |
| 309 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); | |
| 310 | |
| 311 int map_index = Context::FunctionMapIndex(language_mode_, is_generator_); | |
| 312 | |
| 313 // Compute the function map in the current native context and set that | |
| 314 // as the map of the allocated object. | |
| 315 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
| 316 __ movq(rcx, FieldOperand(rcx, GlobalObject::kNativeContextOffset)); | |
| 317 __ movq(rbx, Operand(rcx, Context::SlotOffset(map_index))); | |
| 318 __ movq(FieldOperand(rax, JSObject::kMapOffset), rbx); | |
| 319 | |
| 320 // Initialize the rest of the function. We don't have to update the | |
| 321 // write barrier because the allocated object is in new space. | |
| 322 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); | |
| 323 __ LoadRoot(r8, Heap::kTheHoleValueRootIndex); | |
| 324 __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex); | |
| 325 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); | |
| 326 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rbx); | |
| 327 __ movq(FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset), r8); | |
| 328 __ movq(FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset), rdx); | |
| 329 __ movq(FieldOperand(rax, JSFunction::kContextOffset), rsi); | |
| 330 __ movq(FieldOperand(rax, JSFunction::kLiteralsOffset), rbx); | |
| 331 | |
| 332 // Initialize the code pointer in the function to be the one | |
| 333 // found in the shared function info object. | |
| 334 // But first check if there is an optimized version for our context. | |
| 335 Label check_optimized; | |
| 336 Label install_unoptimized; | |
| 337 if (FLAG_cache_optimized_code) { | |
| 338 __ movq(rbx, | |
| 339 FieldOperand(rdx, SharedFunctionInfo::kOptimizedCodeMapOffset)); | |
| 340 __ testq(rbx, rbx); | |
| 341 __ j(not_zero, &check_optimized, Label::kNear); | |
| 342 } | |
| 343 __ bind(&install_unoptimized); | |
| 344 __ movq(FieldOperand(rax, JSFunction::kNextFunctionLinkOffset), | |
| 345 rdi); // Initialize with undefined. | |
| 346 __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset)); | |
| 347 __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize)); | |
| 348 __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx); | |
| 349 | |
| 350 // Return and remove the on-stack parameter. | |
| 351 __ ret(1 * kPointerSize); | |
| 352 | |
| 353 __ bind(&check_optimized); | |
| 354 | |
| 355 __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1); | |
| 356 | |
| 357 // rcx holds native context, rbx points to fixed array of 3-element entries | |
| 358 // (native context, optimized code, literals). | |
| 359 // The optimized code map must never be empty, so check the first elements. | |
| 360 Label install_optimized; | |
| 361 // Speculatively move code object into edx. | |
| 362 __ movq(rdx, FieldOperand(rbx, SharedFunctionInfo::kFirstCodeSlot)); | |
| 363 __ cmpq(rcx, FieldOperand(rbx, SharedFunctionInfo::kFirstContextSlot)); | |
| 364 __ j(equal, &install_optimized); | |
| 365 | |
| 366 // Iterate through the rest of map backwards. rdx holds an index. | |
| 367 Label loop; | |
| 368 Label restore; | |
| 369 __ movq(rdx, FieldOperand(rbx, FixedArray::kLengthOffset)); | |
| 370 __ SmiToInteger32(rdx, rdx); | |
| 371 __ bind(&loop); | |
| 372 // Do not double check first entry. | |
| 373 __ cmpq(rdx, Immediate(SharedFunctionInfo::kSecondEntryIndex)); | |
| 374 __ j(equal, &restore); | |
| 375 __ subq(rdx, Immediate(SharedFunctionInfo::kEntryLength)); | |
| 376 __ cmpq(rcx, FieldOperand(rbx, | |
| 377 rdx, | |
| 378 times_pointer_size, | |
| 379 FixedArray::kHeaderSize)); | |
| 380 __ j(not_equal, &loop, Label::kNear); | |
| 381 // Hit: fetch the optimized code. | |
| 382 __ movq(rdx, FieldOperand(rbx, | |
| 383 rdx, | |
| 384 times_pointer_size, | |
| 385 FixedArray::kHeaderSize + 1 * kPointerSize)); | |
| 386 | |
| 387 __ bind(&install_optimized); | |
| 388 __ IncrementCounter(counters->fast_new_closure_install_optimized(), 1); | |
| 389 | |
| 390 // TODO(fschneider): Idea: store proper code pointers in the map and either | |
| 391 // unmangle them on marking or do nothing as the whole map is discarded on | |
| 392 // major GC anyway. | |
| 393 __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize)); | |
| 394 __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx); | |
| 395 | |
| 396 // Now link a function into a list of optimized functions. | |
| 397 __ movq(rdx, ContextOperand(rcx, Context::OPTIMIZED_FUNCTIONS_LIST)); | |
| 398 | |
| 399 __ movq(FieldOperand(rax, JSFunction::kNextFunctionLinkOffset), rdx); | |
| 400 // No need for write barrier as JSFunction (rax) is in the new space. | |
| 401 | |
| 402 __ movq(ContextOperand(rcx, Context::OPTIMIZED_FUNCTIONS_LIST), rax); | |
| 403 // Store JSFunction (rax) into rdx before issuing write barrier as | |
| 404 // it clobbers all the registers passed. | |
| 405 __ movq(rdx, rax); | |
| 406 __ RecordWriteContextSlot( | |
| 407 rcx, | |
| 408 Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST), | |
| 409 rdx, | |
| 410 rbx, | |
| 411 kDontSaveFPRegs); | |
| 412 | |
| 413 // Return and remove the on-stack parameter. | |
| 414 __ ret(1 * kPointerSize); | |
| 415 | |
| 416 __ bind(&restore); | |
| 417 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); | |
| 418 __ jmp(&install_unoptimized); | |
| 419 | |
| 420 // Create a new closure through the slower runtime call. | |
| 421 __ bind(&gc); | |
| 422 __ PopReturnAddressTo(rcx); | |
| 423 __ pop(rdx); | |
| 424 __ push(rsi); | |
| 425 __ push(rdx); | |
| 426 __ PushRoot(Heap::kFalseValueRootIndex); | |
| 427 __ PushReturnAddressFrom(rcx); | |
| 428 __ TailCallRuntime(Runtime::kNewClosure, 3, 1); | |
| 429 } | |
| 430 | |
| 431 | |
| 432 void FastNewContextStub::Generate(MacroAssembler* masm) { | 309 void FastNewContextStub::Generate(MacroAssembler* masm) { |
| 433 // Try to allocate the context in new space. | 310 // Try to allocate the context in new space. |
| 434 Label gc; | 311 Label gc; |
| 435 int length = slots_ + Context::MIN_CONTEXT_SLOTS; | 312 int length = slots_ + Context::MIN_CONTEXT_SLOTS; |
| 436 __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize, | 313 __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize, |
| 437 rax, rbx, rcx, &gc, TAG_OBJECT); | 314 rax, rbx, rcx, &gc, TAG_OBJECT); |
| 438 | 315 |
| 439 // Get the function from the stack. | 316 // Get the function from the stack. |
| 440 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); | 317 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 318 __ movq(rcx, args.GetArgumentOperand(0)); |
| 441 | 319 |
| 442 // Set up the object header. | 320 // Set up the object header. |
| 443 __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex); | 321 __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex); |
| 444 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); | 322 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); |
| 445 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); | 323 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); |
| 446 | 324 |
| 447 // Set up the fixed slots. | 325 // Set up the fixed slots. |
| 448 __ Set(rbx, 0); // Set to NULL. | 326 __ Set(rbx, 0); // Set to NULL. |
| 449 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); | 327 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); |
| 450 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi); | 328 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 476 // [rsp + (1 * kPointerSize)] : function | 354 // [rsp + (1 * kPointerSize)] : function |
| 477 // [rsp + (2 * kPointerSize)] : serialized scope info | 355 // [rsp + (2 * kPointerSize)] : serialized scope info |
| 478 | 356 |
| 479 // Try to allocate the context in new space. | 357 // Try to allocate the context in new space. |
| 480 Label gc; | 358 Label gc; |
| 481 int length = slots_ + Context::MIN_CONTEXT_SLOTS; | 359 int length = slots_ + Context::MIN_CONTEXT_SLOTS; |
| 482 __ Allocate(FixedArray::SizeFor(length), | 360 __ Allocate(FixedArray::SizeFor(length), |
| 483 rax, rbx, rcx, &gc, TAG_OBJECT); | 361 rax, rbx, rcx, &gc, TAG_OBJECT); |
| 484 | 362 |
| 485 // Get the function from the stack. | 363 // Get the function from the stack. |
| 486 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); | 364 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 487 | 365 __ movq(rcx, args.GetArgumentOperand(1)); |
| 488 // Get the serialized scope info from the stack. | 366 // Get the serialized scope info from the stack. |
| 489 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); | 367 __ movq(rbx, args.GetArgumentOperand(0)); |
| 490 | 368 |
| 491 // Set up the object header. | 369 // Set up the object header. |
| 492 __ LoadRoot(kScratchRegister, Heap::kBlockContextMapRootIndex); | 370 __ LoadRoot(kScratchRegister, Heap::kBlockContextMapRootIndex); |
| 493 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); | 371 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); |
| 494 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); | 372 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); |
| 495 | 373 |
| 496 // If this block context is nested in the native context we get a smi | 374 // If this block context is nested in the native context we get a smi |
| 497 // sentinel instead of a function. The block context should get the | 375 // sentinel instead of a function. The block context should get the |
| 498 // canonical empty function of the native context as its closure which | 376 // canonical empty function of the native context as its closure which |
| 499 // we still have to look up. | 377 // we still have to look up. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 public: | 431 public: |
| 554 enum ConvertUndefined { | 432 enum ConvertUndefined { |
| 555 CONVERT_UNDEFINED_TO_ZERO, | 433 CONVERT_UNDEFINED_TO_ZERO, |
| 556 BAILOUT_ON_UNDEFINED | 434 BAILOUT_ON_UNDEFINED |
| 557 }; | 435 }; |
| 558 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. | 436 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. |
| 559 // If the operands are not both numbers, jump to not_numbers. | 437 // If the operands are not both numbers, jump to not_numbers. |
| 560 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. | 438 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. |
| 561 // NumberOperands assumes both are smis or heap numbers. | 439 // NumberOperands assumes both are smis or heap numbers. |
| 562 static void LoadSSE2SmiOperands(MacroAssembler* masm); | 440 static void LoadSSE2SmiOperands(MacroAssembler* masm); |
| 563 static void LoadSSE2NumberOperands(MacroAssembler* masm); | |
| 564 static void LoadSSE2UnknownOperands(MacroAssembler* masm, | 441 static void LoadSSE2UnknownOperands(MacroAssembler* masm, |
| 565 Label* not_numbers); | 442 Label* not_numbers); |
| 566 | 443 |
| 567 // Takes the operands in rdx and rax and loads them as integers in rax | 444 // Takes the operands in rdx and rax and loads them as integers in rax |
| 568 // and rcx. | 445 // and rcx. |
| 569 static void LoadAsIntegers(MacroAssembler* masm, | 446 static void LoadAsIntegers(MacroAssembler* masm, |
| 570 Label* operand_conversion_failure, | 447 Label* operand_conversion_failure, |
| 571 Register heap_number_map); | 448 Register heap_number_map); |
| 572 // As above, but we know the operands to be numbers. In that case, | |
| 573 // conversion can't fail. | |
| 574 static void LoadNumbersAsIntegers(MacroAssembler* masm); | |
| 575 | 449 |
| 576 // Tries to convert two values to smis losslessly. | 450 // Tries to convert two values to smis losslessly. |
| 577 // This fails if either argument is not a Smi nor a HeapNumber, | 451 // This fails if either argument is not a Smi nor a HeapNumber, |
| 578 // or if it's a HeapNumber with a value that can't be converted | 452 // or if it's a HeapNumber with a value that can't be converted |
| 579 // losslessly to a Smi. In that case, control transitions to the | 453 // losslessly to a Smi. In that case, control transitions to the |
| 580 // on_not_smis label. | 454 // on_not_smis label. |
| 581 // On success, either control goes to the on_success label (if one is | 455 // On success, either control goes to the on_success label (if one is |
| 582 // provided), or it falls through at the end of the code (if on_success | 456 // provided), or it falls through at the end of the code (if on_success |
| 583 // is NULL). | 457 // is NULL). |
| 584 // On success, both first and second holds Smi tagged values. | 458 // On success, both first and second holds Smi tagged values. |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 // Output: | 1130 // Output: |
| 1257 // xmm1 : untagged double result. | 1131 // xmm1 : untagged double result. |
| 1258 | 1132 |
| 1259 Label runtime_call; | 1133 Label runtime_call; |
| 1260 Label runtime_call_clear_stack; | 1134 Label runtime_call_clear_stack; |
| 1261 Label skip_cache; | 1135 Label skip_cache; |
| 1262 const bool tagged = (argument_type_ == TAGGED); | 1136 const bool tagged = (argument_type_ == TAGGED); |
| 1263 if (tagged) { | 1137 if (tagged) { |
| 1264 Label input_not_smi, loaded; | 1138 Label input_not_smi, loaded; |
| 1265 // Test that rax is a number. | 1139 // Test that rax is a number. |
| 1266 __ movq(rax, Operand(rsp, kPointerSize)); | 1140 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1141 __ movq(rax, args.GetArgumentOperand(0)); |
| 1267 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); | 1142 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); |
| 1268 // Input is a smi. Untag and load it onto the FPU stack. | 1143 // Input is a smi. Untag and load it onto the FPU stack. |
| 1269 // Then load the bits of the double into rbx. | 1144 // Then load the bits of the double into rbx. |
| 1270 __ SmiToInteger32(rax, rax); | 1145 __ SmiToInteger32(rax, rax); |
| 1271 __ subq(rsp, Immediate(kDoubleSize)); | 1146 __ subq(rsp, Immediate(kDoubleSize)); |
| 1272 __ cvtlsi2sd(xmm1, rax); | 1147 __ cvtlsi2sd(xmm1, rax); |
| 1273 __ movsd(Operand(rsp, 0), xmm1); | 1148 __ movsd(Operand(rsp, 0), xmm1); |
| 1274 __ movq(rbx, xmm1); | 1149 __ movq(rbx, xmm1); |
| 1275 __ movq(rdx, xmm1); | 1150 __ movq(rdx, xmm1); |
| 1276 __ fld_d(Operand(rsp, 0)); | 1151 __ fld_d(Operand(rsp, 0)); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1541 ASSERT(type == TranscendentalCache::LOG); | 1416 ASSERT(type == TranscendentalCache::LOG); |
| 1542 __ fldln2(); | 1417 __ fldln2(); |
| 1543 __ fxch(); | 1418 __ fxch(); |
| 1544 __ fyl2x(); | 1419 __ fyl2x(); |
| 1545 } | 1420 } |
| 1546 } | 1421 } |
| 1547 | 1422 |
| 1548 | 1423 |
| 1549 // Input: rdx, rax are the left and right objects of a bit op. | 1424 // Input: rdx, rax are the left and right objects of a bit op. |
| 1550 // Output: rax, rcx are left and right integers for a bit op. | 1425 // Output: rax, rcx are left and right integers for a bit op. |
| 1551 void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm) { | |
| 1552 // Check float operands. | |
| 1553 Label done; | |
| 1554 Label rax_is_smi; | |
| 1555 Label rax_is_object; | |
| 1556 Label rdx_is_object; | |
| 1557 | |
| 1558 __ JumpIfNotSmi(rdx, &rdx_is_object); | |
| 1559 __ SmiToInteger32(rdx, rdx); | |
| 1560 __ JumpIfSmi(rax, &rax_is_smi); | |
| 1561 | |
| 1562 __ bind(&rax_is_object); | |
| 1563 DoubleToIStub stub1(rax, rcx, HeapNumber::kValueOffset - kHeapObjectTag, | |
| 1564 true); | |
| 1565 __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
| 1566 | |
| 1567 __ jmp(&done); | |
| 1568 | |
| 1569 __ bind(&rdx_is_object); | |
| 1570 DoubleToIStub stub2(rdx, rdx, HeapNumber::kValueOffset - kHeapObjectTag, | |
| 1571 true); | |
| 1572 __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
| 1573 __ JumpIfNotSmi(rax, &rax_is_object); | |
| 1574 | |
| 1575 __ bind(&rax_is_smi); | |
| 1576 __ SmiToInteger32(rcx, rax); | |
| 1577 | |
| 1578 __ bind(&done); | |
| 1579 __ movl(rax, rdx); | |
| 1580 } | |
| 1581 | |
| 1582 | |
| 1583 // Input: rdx, rax are the left and right objects of a bit op. | |
| 1584 // Output: rax, rcx are left and right integers for a bit op. | |
| 1585 // Jump to conversion_failure: rdx and rax are unchanged. | 1426 // Jump to conversion_failure: rdx and rax are unchanged. |
| 1586 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, | 1427 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, |
| 1587 Label* conversion_failure, | 1428 Label* conversion_failure, |
| 1588 Register heap_number_map) { | 1429 Register heap_number_map) { |
| 1589 // Check float operands. | 1430 // Check float operands. |
| 1590 Label arg1_is_object, check_undefined_arg1; | 1431 Label arg1_is_object, check_undefined_arg1; |
| 1591 Label arg2_is_object, check_undefined_arg2; | 1432 Label arg2_is_object, check_undefined_arg2; |
| 1592 Label load_arg2, done; | 1433 Label load_arg2, done; |
| 1593 | 1434 |
| 1594 __ JumpIfNotSmi(rdx, &arg1_is_object); | 1435 __ JumpIfNotSmi(rdx, &arg1_is_object); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1638 | 1479 |
| 1639 | 1480 |
| 1640 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { | 1481 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { |
| 1641 __ SmiToInteger32(kScratchRegister, rdx); | 1482 __ SmiToInteger32(kScratchRegister, rdx); |
| 1642 __ cvtlsi2sd(xmm0, kScratchRegister); | 1483 __ cvtlsi2sd(xmm0, kScratchRegister); |
| 1643 __ SmiToInteger32(kScratchRegister, rax); | 1484 __ SmiToInteger32(kScratchRegister, rax); |
| 1644 __ cvtlsi2sd(xmm1, kScratchRegister); | 1485 __ cvtlsi2sd(xmm1, kScratchRegister); |
| 1645 } | 1486 } |
| 1646 | 1487 |
| 1647 | 1488 |
| 1648 void FloatingPointHelper::LoadSSE2NumberOperands(MacroAssembler* masm) { | |
| 1649 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, done; | |
| 1650 // Load operand in rdx into xmm0. | |
| 1651 __ JumpIfSmi(rdx, &load_smi_rdx); | |
| 1652 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | |
| 1653 // Load operand in rax into xmm1. | |
| 1654 __ JumpIfSmi(rax, &load_smi_rax); | |
| 1655 __ bind(&load_nonsmi_rax); | |
| 1656 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | |
| 1657 __ jmp(&done); | |
| 1658 | |
| 1659 __ bind(&load_smi_rdx); | |
| 1660 __ SmiToInteger32(kScratchRegister, rdx); | |
| 1661 __ cvtlsi2sd(xmm0, kScratchRegister); | |
| 1662 __ JumpIfNotSmi(rax, &load_nonsmi_rax); | |
| 1663 | |
| 1664 __ bind(&load_smi_rax); | |
| 1665 __ SmiToInteger32(kScratchRegister, rax); | |
| 1666 __ cvtlsi2sd(xmm1, kScratchRegister); | |
| 1667 | |
| 1668 __ bind(&done); | |
| 1669 } | |
| 1670 | |
| 1671 | |
| 1672 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, | 1489 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, |
| 1673 Label* not_numbers) { | 1490 Label* not_numbers) { |
| 1674 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; | 1491 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; |
| 1675 // Load operand in rdx into xmm0, or branch to not_numbers. | 1492 // Load operand in rdx into xmm0, or branch to not_numbers. |
| 1676 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); | 1493 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); |
| 1677 __ JumpIfSmi(rdx, &load_smi_rdx); | 1494 __ JumpIfSmi(rdx, &load_smi_rdx); |
| 1678 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx); | 1495 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx); |
| 1679 __ j(not_equal, not_numbers); // Argument in rdx is not a number. | 1496 __ j(not_equal, not_numbers); // Argument in rdx is not a number. |
| 1680 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | 1497 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); |
| 1681 // Load operand in rax into xmm1, or branch to not_numbers. | 1498 // Load operand in rax into xmm1, or branch to not_numbers. |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1789 | 1606 |
| 1790 // Save 1 in double_result - we need this several times later on. | 1607 // Save 1 in double_result - we need this several times later on. |
| 1791 __ movq(scratch, Immediate(1)); | 1608 __ movq(scratch, Immediate(1)); |
| 1792 __ cvtlsi2sd(double_result, scratch); | 1609 __ cvtlsi2sd(double_result, scratch); |
| 1793 | 1610 |
| 1794 if (exponent_type_ == ON_STACK) { | 1611 if (exponent_type_ == ON_STACK) { |
| 1795 Label base_is_smi, unpack_exponent; | 1612 Label base_is_smi, unpack_exponent; |
| 1796 // The exponent and base are supplied as arguments on the stack. | 1613 // The exponent and base are supplied as arguments on the stack. |
| 1797 // This can only happen if the stub is called from non-optimized code. | 1614 // This can only happen if the stub is called from non-optimized code. |
| 1798 // Load input parameters from stack. | 1615 // Load input parameters from stack. |
| 1799 __ movq(base, Operand(rsp, 2 * kPointerSize)); | 1616 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1800 __ movq(exponent, Operand(rsp, 1 * kPointerSize)); | 1617 __ movq(base, args.GetArgumentOperand(0)); |
| 1618 __ movq(exponent, args.GetArgumentOperand(1)); |
| 1801 __ JumpIfSmi(base, &base_is_smi, Label::kNear); | 1619 __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
| 1802 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), | 1620 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), |
| 1803 Heap::kHeapNumberMapRootIndex); | 1621 Heap::kHeapNumberMapRootIndex); |
| 1804 __ j(not_equal, &call_runtime); | 1622 __ j(not_equal, &call_runtime); |
| 1805 | 1623 |
| 1806 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); | 1624 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); |
| 1807 __ jmp(&unpack_exponent, Label::kNear); | 1625 __ jmp(&unpack_exponent, Label::kNear); |
| 1808 | 1626 |
| 1809 __ bind(&base_is_smi); | 1627 __ bind(&base_is_smi); |
| 1810 __ SmiToInteger32(base, base); | 1628 __ SmiToInteger32(base, base); |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2223 // rsp[0] : return address | 2041 // rsp[0] : return address |
| 2224 // rsp[8] : number of parameters (tagged) | 2042 // rsp[8] : number of parameters (tagged) |
| 2225 // rsp[16] : receiver displacement | 2043 // rsp[16] : receiver displacement |
| 2226 // rsp[24] : function | 2044 // rsp[24] : function |
| 2227 // Registers used over the whole function: | 2045 // Registers used over the whole function: |
| 2228 // rbx: the mapped parameter count (untagged) | 2046 // rbx: the mapped parameter count (untagged) |
| 2229 // rax: the allocated object (tagged). | 2047 // rax: the allocated object (tagged). |
| 2230 | 2048 |
| 2231 Factory* factory = masm->isolate()->factory(); | 2049 Factory* factory = masm->isolate()->factory(); |
| 2232 | 2050 |
| 2233 __ SmiToInteger64(rbx, Operand(rsp, 1 * kPointerSize)); | 2051 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2052 __ SmiToInteger64(rbx, args.GetArgumentOperand(2)); |
| 2234 // rbx = parameter count (untagged) | 2053 // rbx = parameter count (untagged) |
| 2235 | 2054 |
| 2236 // Check if the calling frame is an arguments adaptor frame. | 2055 // Check if the calling frame is an arguments adaptor frame. |
| 2237 Label runtime; | 2056 Label runtime; |
| 2238 Label adaptor_frame, try_allocate; | 2057 Label adaptor_frame, try_allocate; |
| 2239 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2058 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2240 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); | 2059 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); |
| 2241 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 2060 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2242 __ j(equal, &adaptor_frame); | 2061 __ j(equal, &adaptor_frame); |
| 2243 | 2062 |
| 2244 // No adaptor, parameter count = argument count. | 2063 // No adaptor, parameter count = argument count. |
| 2245 __ movq(rcx, rbx); | 2064 __ movq(rcx, rbx); |
| 2246 __ jmp(&try_allocate, Label::kNear); | 2065 __ jmp(&try_allocate, Label::kNear); |
| 2247 | 2066 |
| 2248 // We have an adaptor frame. Patch the parameters pointer. | 2067 // We have an adaptor frame. Patch the parameters pointer. |
| 2249 __ bind(&adaptor_frame); | 2068 __ bind(&adaptor_frame); |
| 2250 __ SmiToInteger64(rcx, | 2069 __ SmiToInteger64(rcx, |
| 2251 Operand(rdx, | 2070 Operand(rdx, |
| 2252 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2071 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2253 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, | 2072 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, |
| 2254 StandardFrameConstants::kCallerSPOffset)); | 2073 StandardFrameConstants::kCallerSPOffset)); |
| 2255 __ movq(Operand(rsp, 2 * kPointerSize), rdx); | 2074 __ movq(args.GetArgumentOperand(1), rdx); |
| 2256 | 2075 |
| 2257 // rbx = parameter count (untagged) | 2076 // rbx = parameter count (untagged) |
| 2258 // rcx = argument count (untagged) | 2077 // rcx = argument count (untagged) |
| 2259 // Compute the mapped parameter count = min(rbx, rcx) in rbx. | 2078 // Compute the mapped parameter count = min(rbx, rcx) in rbx. |
| 2260 __ cmpq(rbx, rcx); | 2079 __ cmpq(rbx, rcx); |
| 2261 __ j(less_equal, &try_allocate, Label::kNear); | 2080 __ j(less_equal, &try_allocate, Label::kNear); |
| 2262 __ movq(rbx, rcx); | 2081 __ movq(rbx, rcx); |
| 2263 | 2082 |
| 2264 __ bind(&try_allocate); | 2083 __ bind(&try_allocate); |
| 2265 | 2084 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2306 // rcx = argument count (untagged) | 2125 // rcx = argument count (untagged) |
| 2307 // rdi = address of boilerplate object (tagged) | 2126 // rdi = address of boilerplate object (tagged) |
| 2308 // Copy the JS object part. | 2127 // Copy the JS object part. |
| 2309 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { | 2128 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
| 2310 __ movq(rdx, FieldOperand(rdi, i)); | 2129 __ movq(rdx, FieldOperand(rdi, i)); |
| 2311 __ movq(FieldOperand(rax, i), rdx); | 2130 __ movq(FieldOperand(rax, i), rdx); |
| 2312 } | 2131 } |
| 2313 | 2132 |
| 2314 // Set up the callee in-object property. | 2133 // Set up the callee in-object property. |
| 2315 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | 2134 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); |
| 2316 __ movq(rdx, Operand(rsp, 3 * kPointerSize)); | 2135 __ movq(rdx, args.GetArgumentOperand(0)); |
| 2317 __ movq(FieldOperand(rax, JSObject::kHeaderSize + | 2136 __ movq(FieldOperand(rax, JSObject::kHeaderSize + |
| 2318 Heap::kArgumentsCalleeIndex * kPointerSize), | 2137 Heap::kArgumentsCalleeIndex * kPointerSize), |
| 2319 rdx); | 2138 rdx); |
| 2320 | 2139 |
| 2321 // Use the length (smi tagged) and set that as an in-object property too. | 2140 // Use the length (smi tagged) and set that as an in-object property too. |
| 2322 // Note: rcx is tagged from here on. | 2141 // Note: rcx is tagged from here on. |
| 2323 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 2142 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 2324 __ Integer32ToSmi(rcx, rcx); | 2143 __ Integer32ToSmi(rcx, rcx); |
| 2325 __ movq(FieldOperand(rax, JSObject::kHeaderSize + | 2144 __ movq(FieldOperand(rax, JSObject::kHeaderSize + |
| 2326 Heap::kArgumentsLengthIndex * kPointerSize), | 2145 Heap::kArgumentsLengthIndex * kPointerSize), |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2357 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | 2176 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 |
| 2358 // The mapped parameter thus need to get indices | 2177 // The mapped parameter thus need to get indices |
| 2359 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | 2178 // MIN_CONTEXT_SLOTS+parameter_count-1 .. |
| 2360 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | 2179 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count |
| 2361 // We loop from right to left. | 2180 // We loop from right to left. |
| 2362 Label parameters_loop, parameters_test; | 2181 Label parameters_loop, parameters_test; |
| 2363 | 2182 |
| 2364 // Load tagged parameter count into r9. | 2183 // Load tagged parameter count into r9. |
| 2365 __ Integer32ToSmi(r9, rbx); | 2184 __ Integer32ToSmi(r9, rbx); |
| 2366 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); | 2185 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); |
| 2367 __ addq(r8, Operand(rsp, 1 * kPointerSize)); | 2186 __ addq(r8, args.GetArgumentOperand(2)); |
| 2368 __ subq(r8, r9); | 2187 __ subq(r8, r9); |
| 2369 __ Move(r11, factory->the_hole_value()); | 2188 __ Move(r11, factory->the_hole_value()); |
| 2370 __ movq(rdx, rdi); | 2189 __ movq(rdx, rdi); |
| 2371 __ lea(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); | 2190 __ lea(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); |
| 2372 // r9 = loop variable (tagged) | 2191 // r9 = loop variable (tagged) |
| 2373 // r8 = mapping index (tagged) | 2192 // r8 = mapping index (tagged) |
| 2374 // r11 = the hole value | 2193 // r11 = the hole value |
| 2375 // rdx = address of parameter map (tagged) | 2194 // rdx = address of parameter map (tagged) |
| 2376 // rdi = address of backing store (tagged) | 2195 // rdi = address of backing store (tagged) |
| 2377 __ jmp(¶meters_test, Label::kNear); | 2196 __ jmp(¶meters_test, Label::kNear); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2396 | 2215 |
| 2397 // rcx = argument count (tagged) | 2216 // rcx = argument count (tagged) |
| 2398 // rdi = address of backing store (tagged) | 2217 // rdi = address of backing store (tagged) |
| 2399 // Copy arguments header and remaining slots (if there are any). | 2218 // Copy arguments header and remaining slots (if there are any). |
| 2400 __ Move(FieldOperand(rdi, FixedArray::kMapOffset), | 2219 __ Move(FieldOperand(rdi, FixedArray::kMapOffset), |
| 2401 factory->fixed_array_map()); | 2220 factory->fixed_array_map()); |
| 2402 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); | 2221 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); |
| 2403 | 2222 |
| 2404 Label arguments_loop, arguments_test; | 2223 Label arguments_loop, arguments_test; |
| 2405 __ movq(r8, rbx); | 2224 __ movq(r8, rbx); |
| 2406 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2225 __ movq(rdx, args.GetArgumentOperand(1)); |
| 2407 // Untag rcx for the loop below. | 2226 // Untag rcx for the loop below. |
| 2408 __ SmiToInteger64(rcx, rcx); | 2227 __ SmiToInteger64(rcx, rcx); |
| 2409 __ lea(kScratchRegister, Operand(r8, times_pointer_size, 0)); | 2228 __ lea(kScratchRegister, Operand(r8, times_pointer_size, 0)); |
| 2410 __ subq(rdx, kScratchRegister); | 2229 __ subq(rdx, kScratchRegister); |
| 2411 __ jmp(&arguments_test, Label::kNear); | 2230 __ jmp(&arguments_test, Label::kNear); |
| 2412 | 2231 |
| 2413 __ bind(&arguments_loop); | 2232 __ bind(&arguments_loop); |
| 2414 __ subq(rdx, Immediate(kPointerSize)); | 2233 __ subq(rdx, Immediate(kPointerSize)); |
| 2415 __ movq(r9, Operand(rdx, 0)); | 2234 __ movq(r9, Operand(rdx, 0)); |
| 2416 __ movq(FieldOperand(rdi, r8, | 2235 __ movq(FieldOperand(rdi, r8, |
| 2417 times_pointer_size, | 2236 times_pointer_size, |
| 2418 FixedArray::kHeaderSize), | 2237 FixedArray::kHeaderSize), |
| 2419 r9); | 2238 r9); |
| 2420 __ addq(r8, Immediate(1)); | 2239 __ addq(r8, Immediate(1)); |
| 2421 | 2240 |
| 2422 __ bind(&arguments_test); | 2241 __ bind(&arguments_test); |
| 2423 __ cmpq(r8, rcx); | 2242 __ cmpq(r8, rcx); |
| 2424 __ j(less, &arguments_loop, Label::kNear); | 2243 __ j(less, &arguments_loop, Label::kNear); |
| 2425 | 2244 |
| 2426 // Return and remove the on-stack parameters. | 2245 // Return and remove the on-stack parameters. |
| 2427 __ ret(3 * kPointerSize); | 2246 __ ret(3 * kPointerSize); |
| 2428 | 2247 |
| 2429 // Do the runtime call to allocate the arguments object. | 2248 // Do the runtime call to allocate the arguments object. |
| 2430 // rcx = argument count (untagged) | 2249 // rcx = argument count (untagged) |
| 2431 __ bind(&runtime); | 2250 __ bind(&runtime); |
| 2432 __ Integer32ToSmi(rcx, rcx); | 2251 __ Integer32ToSmi(rcx, rcx); |
| 2433 __ movq(Operand(rsp, 1 * kPointerSize), rcx); // Patch argument count. | 2252 __ movq(args.GetArgumentOperand(2), rcx); // Patch argument count. |
| 2434 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); | 2253 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); |
| 2435 } | 2254 } |
| 2436 | 2255 |
| 2437 | 2256 |
| 2438 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { | 2257 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { |
| 2439 // rsp[0] : return address | 2258 // rsp[0] : return address |
| 2440 // rsp[8] : number of parameters | 2259 // rsp[8] : number of parameters |
| 2441 // rsp[16] : receiver displacement | 2260 // rsp[16] : receiver displacement |
| 2442 // rsp[24] : function | 2261 // rsp[24] : function |
| 2443 | 2262 |
| 2444 // Check if the calling frame is an arguments adaptor frame. | 2263 // Check if the calling frame is an arguments adaptor frame. |
| 2445 Label runtime; | 2264 Label runtime; |
| 2446 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2265 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2447 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); | 2266 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); |
| 2448 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 2267 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2449 __ j(not_equal, &runtime); | 2268 __ j(not_equal, &runtime); |
| 2450 | 2269 |
| 2451 // Patch the arguments.length and the parameters pointer. | 2270 // Patch the arguments.length and the parameters pointer. |
| 2271 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2452 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2272 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2453 __ movq(Operand(rsp, 1 * kPointerSize), rcx); | 2273 __ movq(args.GetArgumentOperand(2), rcx); |
| 2454 __ SmiToInteger64(rcx, rcx); | 2274 __ SmiToInteger64(rcx, rcx); |
| 2455 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, | 2275 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, |
| 2456 StandardFrameConstants::kCallerSPOffset)); | 2276 StandardFrameConstants::kCallerSPOffset)); |
| 2457 __ movq(Operand(rsp, 2 * kPointerSize), rdx); | 2277 __ movq(args.GetArgumentOperand(1), rdx); |
| 2458 | 2278 |
| 2459 __ bind(&runtime); | 2279 __ bind(&runtime); |
| 2460 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); | 2280 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); |
| 2461 } | 2281 } |
| 2462 | 2282 |
| 2463 | 2283 |
| 2464 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | 2284 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
| 2465 // rsp[0] : return address | 2285 // rsp[0] : return address |
| 2466 // rsp[8] : number of parameters | 2286 // rsp[8] : number of parameters |
| 2467 // rsp[16] : receiver displacement | 2287 // rsp[16] : receiver displacement |
| 2468 // rsp[24] : function | 2288 // rsp[24] : function |
| 2469 | 2289 |
| 2470 // Check if the calling frame is an arguments adaptor frame. | 2290 // Check if the calling frame is an arguments adaptor frame. |
| 2471 Label adaptor_frame, try_allocate, runtime; | 2291 Label adaptor_frame, try_allocate, runtime; |
| 2472 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2292 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2473 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); | 2293 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); |
| 2474 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 2294 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2475 __ j(equal, &adaptor_frame); | 2295 __ j(equal, &adaptor_frame); |
| 2476 | 2296 |
| 2477 // Get the length from the frame. | 2297 // Get the length from the frame. |
| 2478 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); | 2298 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2299 __ movq(rcx, args.GetArgumentOperand(2)); |
| 2479 __ SmiToInteger64(rcx, rcx); | 2300 __ SmiToInteger64(rcx, rcx); |
| 2480 __ jmp(&try_allocate); | 2301 __ jmp(&try_allocate); |
| 2481 | 2302 |
| 2482 // Patch the arguments.length and the parameters pointer. | 2303 // Patch the arguments.length and the parameters pointer. |
| 2483 __ bind(&adaptor_frame); | 2304 __ bind(&adaptor_frame); |
| 2484 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2305 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2485 __ movq(Operand(rsp, 1 * kPointerSize), rcx); | 2306 __ movq(args.GetArgumentOperand(2), rcx); |
| 2486 __ SmiToInteger64(rcx, rcx); | 2307 __ SmiToInteger64(rcx, rcx); |
| 2487 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, | 2308 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, |
| 2488 StandardFrameConstants::kCallerSPOffset)); | 2309 StandardFrameConstants::kCallerSPOffset)); |
| 2489 __ movq(Operand(rsp, 2 * kPointerSize), rdx); | 2310 __ movq(args.GetArgumentOperand(1), rdx); |
| 2490 | 2311 |
| 2491 // Try the new space allocation. Start out with computing the size of | 2312 // Try the new space allocation. Start out with computing the size of |
| 2492 // the arguments object and the elements array. | 2313 // the arguments object and the elements array. |
| 2493 Label add_arguments_object; | 2314 Label add_arguments_object; |
| 2494 __ bind(&try_allocate); | 2315 __ bind(&try_allocate); |
| 2495 __ testq(rcx, rcx); | 2316 __ testq(rcx, rcx); |
| 2496 __ j(zero, &add_arguments_object, Label::kNear); | 2317 __ j(zero, &add_arguments_object, Label::kNear); |
| 2497 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); | 2318 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); |
| 2498 __ bind(&add_arguments_object); | 2319 __ bind(&add_arguments_object); |
| 2499 __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict)); | 2320 __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict)); |
| 2500 | 2321 |
| 2501 // Do the allocation of both objects in one go. | 2322 // Do the allocation of both objects in one go. |
| 2502 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); | 2323 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); |
| 2503 | 2324 |
| 2504 // Get the arguments boilerplate from the current native context. | 2325 // Get the arguments boilerplate from the current native context. |
| 2505 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 2326 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 2506 __ movq(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); | 2327 __ movq(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); |
| 2507 const int offset = | 2328 const int offset = |
| 2508 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX); | 2329 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX); |
| 2509 __ movq(rdi, Operand(rdi, offset)); | 2330 __ movq(rdi, Operand(rdi, offset)); |
| 2510 | 2331 |
| 2511 // Copy the JS object part. | 2332 // Copy the JS object part. |
| 2512 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { | 2333 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
| 2513 __ movq(rbx, FieldOperand(rdi, i)); | 2334 __ movq(rbx, FieldOperand(rdi, i)); |
| 2514 __ movq(FieldOperand(rax, i), rbx); | 2335 __ movq(FieldOperand(rax, i), rbx); |
| 2515 } | 2336 } |
| 2516 | 2337 |
| 2517 // Get the length (smi tagged) and set that as an in-object property too. | 2338 // Get the length (smi tagged) and set that as an in-object property too. |
| 2518 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 2339 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 2519 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); | 2340 __ movq(rcx, args.GetArgumentOperand(2)); |
| 2520 __ movq(FieldOperand(rax, JSObject::kHeaderSize + | 2341 __ movq(FieldOperand(rax, JSObject::kHeaderSize + |
| 2521 Heap::kArgumentsLengthIndex * kPointerSize), | 2342 Heap::kArgumentsLengthIndex * kPointerSize), |
| 2522 rcx); | 2343 rcx); |
| 2523 | 2344 |
| 2524 // If there are no actual arguments, we're done. | 2345 // If there are no actual arguments, we're done. |
| 2525 Label done; | 2346 Label done; |
| 2526 __ testq(rcx, rcx); | 2347 __ testq(rcx, rcx); |
| 2527 __ j(zero, &done); | 2348 __ j(zero, &done); |
| 2528 | 2349 |
| 2529 // Get the parameters pointer from the stack. | 2350 // Get the parameters pointer from the stack. |
| 2530 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2351 __ movq(rdx, args.GetArgumentOperand(1)); |
| 2531 | 2352 |
| 2532 // Set up the elements pointer in the allocated arguments object and | 2353 // Set up the elements pointer in the allocated arguments object and |
| 2533 // initialize the header in the elements fixed array. | 2354 // initialize the header in the elements fixed array. |
| 2534 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict)); | 2355 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict)); |
| 2535 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); | 2356 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
| 2536 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); | 2357 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); |
| 2537 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | 2358 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
| 2538 | 2359 |
| 2539 | 2360 |
| 2540 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); | 2361 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3003 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); | 2824 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); |
| 3004 __ jmp(&check_underlying); | 2825 __ jmp(&check_underlying); |
| 3005 #endif // V8_INTERPRETED_REGEXP | 2826 #endif // V8_INTERPRETED_REGEXP |
| 3006 } | 2827 } |
| 3007 | 2828 |
| 3008 | 2829 |
| 3009 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 2830 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
| 3010 const int kMaxInlineLength = 100; | 2831 const int kMaxInlineLength = 100; |
| 3011 Label slowcase; | 2832 Label slowcase; |
| 3012 Label done; | 2833 Label done; |
| 3013 __ movq(r8, Operand(rsp, kPointerSize * 3)); | 2834 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2835 __ movq(r8, args.GetArgumentOperand(0)); |
| 3014 __ JumpIfNotSmi(r8, &slowcase); | 2836 __ JumpIfNotSmi(r8, &slowcase); |
| 3015 __ SmiToInteger32(rbx, r8); | 2837 __ SmiToInteger32(rbx, r8); |
| 3016 __ cmpl(rbx, Immediate(kMaxInlineLength)); | 2838 __ cmpl(rbx, Immediate(kMaxInlineLength)); |
| 3017 __ j(above, &slowcase); | 2839 __ j(above, &slowcase); |
| 3018 // Smi-tagging is equivalent to multiplying by 2. | 2840 // Smi-tagging is equivalent to multiplying by 2. |
| 3019 STATIC_ASSERT(kSmiTag == 0); | 2841 STATIC_ASSERT(kSmiTag == 0); |
| 3020 STATIC_ASSERT(kSmiTagSize == 1); | 2842 STATIC_ASSERT(kSmiTagSize == 1); |
| 3021 // Allocate RegExpResult followed by FixedArray with size in rbx. | 2843 // Allocate RegExpResult followed by FixedArray with size in rbx. |
| 3022 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] | 2844 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] |
| 3023 // Elements: [Map][Length][..elements..] | 2845 // Elements: [Map][Length][..elements..] |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3041 | 2863 |
| 3042 // Set empty properties FixedArray. | 2864 // Set empty properties FixedArray. |
| 3043 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); | 2865 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); |
| 3044 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); | 2866 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); |
| 3045 | 2867 |
| 3046 // Set elements to point to FixedArray allocated right after the JSArray. | 2868 // Set elements to point to FixedArray allocated right after the JSArray. |
| 3047 __ lea(rcx, Operand(rax, JSRegExpResult::kSize)); | 2869 __ lea(rcx, Operand(rax, JSRegExpResult::kSize)); |
| 3048 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx); | 2870 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx); |
| 3049 | 2871 |
| 3050 // Set input, index and length fields from arguments. | 2872 // Set input, index and length fields from arguments. |
| 3051 __ movq(r8, Operand(rsp, kPointerSize * 1)); | 2873 __ movq(r8, args.GetArgumentOperand(2)); |
| 3052 __ movq(FieldOperand(rax, JSRegExpResult::kInputOffset), r8); | 2874 __ movq(FieldOperand(rax, JSRegExpResult::kInputOffset), r8); |
| 3053 __ movq(r8, Operand(rsp, kPointerSize * 2)); | 2875 __ movq(r8, args.GetArgumentOperand(1)); |
| 3054 __ movq(FieldOperand(rax, JSRegExpResult::kIndexOffset), r8); | 2876 __ movq(FieldOperand(rax, JSRegExpResult::kIndexOffset), r8); |
| 3055 __ movq(r8, Operand(rsp, kPointerSize * 3)); | 2877 __ movq(r8, args.GetArgumentOperand(0)); |
| 3056 __ movq(FieldOperand(rax, JSArray::kLengthOffset), r8); | 2878 __ movq(FieldOperand(rax, JSArray::kLengthOffset), r8); |
| 3057 | 2879 |
| 3058 // Fill out the elements FixedArray. | 2880 // Fill out the elements FixedArray. |
| 3059 // rax: JSArray. | 2881 // rax: JSArray. |
| 3060 // rcx: FixedArray. | 2882 // rcx: FixedArray. |
| 3061 // rbx: Number of elements in array as int32. | 2883 // rbx: Number of elements in array as int32. |
| 3062 | 2884 |
| 3063 // Set map. | 2885 // Set map. |
| 3064 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); | 2886 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); |
| 3065 __ movq(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister); | 2887 __ movq(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3176 // but times_twice_pointer_size (multiplication by 16) scale factor | 2998 // but times_twice_pointer_size (multiplication by 16) scale factor |
| 3177 // is not supported by addrmode on x64 platform. | 2999 // is not supported by addrmode on x64 platform. |
| 3178 // So we have to premultiply entry index before lookup. | 3000 // So we have to premultiply entry index before lookup. |
| 3179 __ shl(hash, Immediate(kPointerSizeLog2 + 1)); | 3001 __ shl(hash, Immediate(kPointerSizeLog2 + 1)); |
| 3180 } | 3002 } |
| 3181 | 3003 |
| 3182 | 3004 |
| 3183 void NumberToStringStub::Generate(MacroAssembler* masm) { | 3005 void NumberToStringStub::Generate(MacroAssembler* masm) { |
| 3184 Label runtime; | 3006 Label runtime; |
| 3185 | 3007 |
| 3186 __ movq(rbx, Operand(rsp, kPointerSize)); | 3008 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 3009 __ movq(rbx, args.GetArgumentOperand(0)); |
| 3187 | 3010 |
| 3188 // Generate code to lookup number in the number string cache. | 3011 // Generate code to lookup number in the number string cache. |
| 3189 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, &runtime); | 3012 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, &runtime); |
| 3190 __ ret(1 * kPointerSize); | 3013 __ ret(1 * kPointerSize); |
| 3191 | 3014 |
| 3192 __ bind(&runtime); | 3015 __ bind(&runtime); |
| 3193 // Handle number to string in the runtime system if not found in the cache. | 3016 // Handle number to string in the runtime system if not found in the cache. |
| 3194 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); | 3017 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); |
| 3195 } | 3018 } |
| 3196 | 3019 |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3587 | 3410 |
| 3588 __ bind(&done); | 3411 __ bind(&done); |
| 3589 } | 3412 } |
| 3590 | 3413 |
| 3591 | 3414 |
| 3592 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3415 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3593 // rbx : cache cell for call target | 3416 // rbx : cache cell for call target |
| 3594 // rdi : the function to call | 3417 // rdi : the function to call |
| 3595 Isolate* isolate = masm->isolate(); | 3418 Isolate* isolate = masm->isolate(); |
| 3596 Label slow, non_function; | 3419 Label slow, non_function; |
| 3420 StackArgumentsAccessor args(rsp, argc_); |
| 3597 | 3421 |
| 3598 // The receiver might implicitly be the global object. This is | 3422 // The receiver might implicitly be the global object. This is |
| 3599 // indicated by passing the hole as the receiver to the call | 3423 // indicated by passing the hole as the receiver to the call |
| 3600 // function stub. | 3424 // function stub. |
| 3601 if (ReceiverMightBeImplicit()) { | 3425 if (ReceiverMightBeImplicit()) { |
| 3602 Label call; | 3426 Label call; |
| 3603 // Get the receiver from the stack. | 3427 // Get the receiver from the stack. |
| 3604 // +1 ~ return address | 3428 __ movq(rax, args.GetReceiverOperand()); |
| 3605 __ movq(rax, Operand(rsp, (argc_ + 1) * kPointerSize)); | |
| 3606 // Call as function is indicated with the hole. | 3429 // Call as function is indicated with the hole. |
| 3607 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 3430 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
| 3608 __ j(not_equal, &call, Label::kNear); | 3431 __ j(not_equal, &call, Label::kNear); |
| 3609 // Patch the receiver on the stack with the global receiver object. | 3432 // Patch the receiver on the stack with the global receiver object. |
| 3610 __ movq(rcx, GlobalObjectOperand()); | 3433 __ movq(rcx, GlobalObjectOperand()); |
| 3611 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); | 3434 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
| 3612 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rcx); | 3435 __ movq(args.GetReceiverOperand(), rcx); |
| 3613 __ bind(&call); | 3436 __ bind(&call); |
| 3614 } | 3437 } |
| 3615 | 3438 |
| 3616 // Check that the function really is a JavaScript function. | 3439 // Check that the function really is a JavaScript function. |
| 3617 __ JumpIfSmi(rdi, &non_function); | 3440 __ JumpIfSmi(rdi, &non_function); |
| 3618 // Goto slow case if we do not have a function. | 3441 // Goto slow case if we do not have a function. |
| 3619 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 3442 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 3620 __ j(not_equal, &slow); | 3443 __ j(not_equal, &slow); |
| 3621 | 3444 |
| 3622 if (RecordCallTarget()) { | 3445 if (RecordCallTarget()) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3664 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 3487 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
| 3665 { | 3488 { |
| 3666 Handle<Code> adaptor = | 3489 Handle<Code> adaptor = |
| 3667 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3490 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 3668 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 3491 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
| 3669 } | 3492 } |
| 3670 | 3493 |
| 3671 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 3494 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 3672 // of the original receiver from the call site). | 3495 // of the original receiver from the call site). |
| 3673 __ bind(&non_function); | 3496 __ bind(&non_function); |
| 3674 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); | 3497 __ movq(args.GetReceiverOperand(), rdi); |
| 3675 __ Set(rax, argc_); | 3498 __ Set(rax, argc_); |
| 3676 __ Set(rbx, 0); | 3499 __ Set(rbx, 0); |
| 3677 __ SetCallKind(rcx, CALL_AS_METHOD); | 3500 __ SetCallKind(rcx, CALL_AS_METHOD); |
| 3678 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 3501 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
| 3679 Handle<Code> adaptor = | 3502 Handle<Code> adaptor = |
| 3680 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); | 3503 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); |
| 3681 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3504 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 3682 } | 3505 } |
| 3683 | 3506 |
| 3684 | 3507 |
| (...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4199 // Move(kScratchRegister, Factory::the_hole_value()) | 4022 // Move(kScratchRegister, Factory::the_hole_value()) |
| 4200 // in front of the hole value address. | 4023 // in front of the hole value address. |
| 4201 static const unsigned int kWordBeforeMapCheckValue = 0xBA49FF78; | 4024 static const unsigned int kWordBeforeMapCheckValue = 0xBA49FF78; |
| 4202 // The last 4 bytes of the instruction sequence | 4025 // The last 4 bytes of the instruction sequence |
| 4203 // __ j(not_equal, &cache_miss); | 4026 // __ j(not_equal, &cache_miss); |
| 4204 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 4027 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
| 4205 // before the offset of the hole value in the root array. | 4028 // before the offset of the hole value in the root array. |
| 4206 static const unsigned int kWordBeforeResultValue = 0x458B4909; | 4029 static const unsigned int kWordBeforeResultValue = 0x458B4909; |
| 4207 // Only the inline check flag is supported on X64. | 4030 // Only the inline check flag is supported on X64. |
| 4208 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck()); | 4031 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck()); |
| 4209 int extra_stack_space = HasCallSiteInlineCheck() ? kPointerSize : 0; | 4032 int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0; |
| 4210 | 4033 |
| 4211 // Get the object - go slow case if it's a smi. | 4034 // Get the object - go slow case if it's a smi. |
| 4212 Label slow; | 4035 Label slow; |
| 4213 | 4036 StackArgumentsAccessor args(rsp, 2 + extra_argument_offset, |
| 4214 __ movq(rax, Operand(rsp, 2 * kPointerSize + extra_stack_space)); | 4037 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 4038 __ movq(rax, args.GetArgumentOperand(0)); |
| 4215 __ JumpIfSmi(rax, &slow); | 4039 __ JumpIfSmi(rax, &slow); |
| 4216 | 4040 |
| 4217 // Check that the left hand is a JS object. Leave its map in rax. | 4041 // Check that the left hand is a JS object. Leave its map in rax. |
| 4218 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax); | 4042 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax); |
| 4219 __ j(below, &slow); | 4043 __ j(below, &slow); |
| 4220 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); | 4044 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); |
| 4221 __ j(above, &slow); | 4045 __ j(above, &slow); |
| 4222 | 4046 |
| 4223 // Get the prototype of the function. | 4047 // Get the prototype of the function. |
| 4224 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space)); | 4048 __ movq(rdx, args.GetArgumentOperand(1)); |
| 4225 // rdx is function, rax is map. | 4049 // rdx is function, rax is map. |
| 4226 | 4050 |
| 4227 // If there is a call site cache don't look in the global cache, but do the | 4051 // If there is a call site cache don't look in the global cache, but do the |
| 4228 // real lookup and update the call site cache. | 4052 // real lookup and update the call site cache. |
| 4229 if (!HasCallSiteInlineCheck()) { | 4053 if (!HasCallSiteInlineCheck()) { |
| 4230 // Look up the function and the map in the instanceof cache. | 4054 // Look up the function and the map in the instanceof cache. |
| 4231 Label miss; | 4055 Label miss; |
| 4232 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); | 4056 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); |
| 4233 __ j(not_equal, &miss, Label::kNear); | 4057 __ j(not_equal, &miss, Label::kNear); |
| 4234 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); | 4058 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4249 | 4073 |
| 4250 // Register mapping: | 4074 // Register mapping: |
| 4251 // rax is object map. | 4075 // rax is object map. |
| 4252 // rdx is function. | 4076 // rdx is function. |
| 4253 // rbx is function prototype. | 4077 // rbx is function prototype. |
| 4254 if (!HasCallSiteInlineCheck()) { | 4078 if (!HasCallSiteInlineCheck()) { |
| 4255 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); | 4079 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); |
| 4256 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); | 4080 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); |
| 4257 } else { | 4081 } else { |
| 4258 // Get return address and delta to inlined map check. | 4082 // Get return address and delta to inlined map check. |
| 4259 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); | 4083 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
| 4260 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); | 4084 __ subq(kScratchRegister, args.GetArgumentOperand(2)); |
| 4261 if (FLAG_debug_code) { | 4085 if (FLAG_debug_code) { |
| 4262 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); | 4086 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); |
| 4263 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); | 4087 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); |
| 4264 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); | 4088 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); |
| 4265 } | 4089 } |
| 4266 __ movq(kScratchRegister, | 4090 __ movq(kScratchRegister, |
| 4267 Operand(kScratchRegister, kOffsetToMapCheckValue)); | 4091 Operand(kScratchRegister, kOffsetToMapCheckValue)); |
| 4268 __ movq(Operand(kScratchRegister, 0), rax); | 4092 __ movq(Operand(kScratchRegister, 0), rax); |
| 4269 } | 4093 } |
| 4270 | 4094 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4290 // Store bitwise zero in the cache. This is a Smi in GC terms. | 4114 // Store bitwise zero in the cache. This is a Smi in GC terms. |
| 4291 STATIC_ASSERT(kSmiTag == 0); | 4115 STATIC_ASSERT(kSmiTag == 0); |
| 4292 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); | 4116 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); |
| 4293 } else { | 4117 } else { |
| 4294 // Store offset of true in the root array at the inline check site. | 4118 // Store offset of true in the root array at the inline check site. |
| 4295 int true_offset = 0x100 + | 4119 int true_offset = 0x100 + |
| 4296 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; | 4120 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; |
| 4297 // Assert it is a 1-byte signed value. | 4121 // Assert it is a 1-byte signed value. |
| 4298 ASSERT(true_offset >= 0 && true_offset < 0x100); | 4122 ASSERT(true_offset >= 0 && true_offset < 0x100); |
| 4299 __ movl(rax, Immediate(true_offset)); | 4123 __ movl(rax, Immediate(true_offset)); |
| 4300 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); | 4124 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
| 4301 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); | 4125 __ subq(kScratchRegister, args.GetArgumentOperand(2)); |
| 4302 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 4126 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
| 4303 if (FLAG_debug_code) { | 4127 if (FLAG_debug_code) { |
| 4304 __ movl(rax, Immediate(kWordBeforeResultValue)); | 4128 __ movl(rax, Immediate(kWordBeforeResultValue)); |
| 4305 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 4129 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
| 4306 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 4130 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
| 4307 } | 4131 } |
| 4308 __ Set(rax, 0); | 4132 __ Set(rax, 0); |
| 4309 } | 4133 } |
| 4310 __ ret(2 * kPointerSize + extra_stack_space); | 4134 __ ret((2 + extra_argument_offset) * kPointerSize); |
| 4311 | 4135 |
| 4312 __ bind(&is_not_instance); | 4136 __ bind(&is_not_instance); |
| 4313 if (!HasCallSiteInlineCheck()) { | 4137 if (!HasCallSiteInlineCheck()) { |
| 4314 // We have to store a non-zero value in the cache. | 4138 // We have to store a non-zero value in the cache. |
| 4315 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); | 4139 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); |
| 4316 } else { | 4140 } else { |
| 4317 // Store offset of false in the root array at the inline check site. | 4141 // Store offset of false in the root array at the inline check site. |
| 4318 int false_offset = 0x100 + | 4142 int false_offset = 0x100 + |
| 4319 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; | 4143 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; |
| 4320 // Assert it is a 1-byte signed value. | 4144 // Assert it is a 1-byte signed value. |
| 4321 ASSERT(false_offset >= 0 && false_offset < 0x100); | 4145 ASSERT(false_offset >= 0 && false_offset < 0x100); |
| 4322 __ movl(rax, Immediate(false_offset)); | 4146 __ movl(rax, Immediate(false_offset)); |
| 4323 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); | 4147 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
| 4324 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); | 4148 __ subq(kScratchRegister, args.GetArgumentOperand(2)); |
| 4325 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 4149 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
| 4326 if (FLAG_debug_code) { | 4150 if (FLAG_debug_code) { |
| 4327 __ movl(rax, Immediate(kWordBeforeResultValue)); | 4151 __ movl(rax, Immediate(kWordBeforeResultValue)); |
| 4328 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 4152 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
| 4329 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 4153 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
| 4330 } | 4154 } |
| 4331 } | 4155 } |
| 4332 __ ret(2 * kPointerSize + extra_stack_space); | 4156 __ ret((2 + extra_argument_offset) * kPointerSize); |
| 4333 | 4157 |
| 4334 // Slow-case: Go through the JavaScript implementation. | 4158 // Slow-case: Go through the JavaScript implementation. |
| 4335 __ bind(&slow); | 4159 __ bind(&slow); |
| 4336 if (HasCallSiteInlineCheck()) { | 4160 if (HasCallSiteInlineCheck()) { |
| 4337 // Remove extra value from the stack. | 4161 // Remove extra value from the stack. |
| 4338 __ PopReturnAddressTo(rcx); | 4162 __ PopReturnAddressTo(rcx); |
| 4339 __ pop(rax); | 4163 __ pop(rax); |
| 4340 __ PushReturnAddressFrom(rcx); | 4164 __ PushReturnAddressFrom(rcx); |
| 4341 } | 4165 } |
| 4342 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 4166 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4480 | 4304 |
| 4481 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 4305 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
| 4482 } | 4306 } |
| 4483 | 4307 |
| 4484 | 4308 |
| 4485 void StringAddStub::Generate(MacroAssembler* masm) { | 4309 void StringAddStub::Generate(MacroAssembler* masm) { |
| 4486 Label call_runtime, call_builtin; | 4310 Label call_runtime, call_builtin; |
| 4487 Builtins::JavaScript builtin_id = Builtins::ADD; | 4311 Builtins::JavaScript builtin_id = Builtins::ADD; |
| 4488 | 4312 |
| 4489 // Load the two arguments. | 4313 // Load the two arguments. |
| 4490 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument (left). | 4314 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 4491 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right). | 4315 __ movq(rax, args.GetArgumentOperand(0)); // First argument (left). |
| 4316 __ movq(rdx, args.GetArgumentOperand(1)); // Second argument (right). |
| 4492 | 4317 |
| 4493 // Make sure that both arguments are strings if not known in advance. | 4318 // Make sure that both arguments are strings if not known in advance. |
| 4494 // Otherwise, at least one of the arguments is definitely a string, | 4319 // Otherwise, at least one of the arguments is definitely a string, |
| 4495 // and we convert the one that is not known to be a string. | 4320 // and we convert the one that is not known to be a string. |
| 4496 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { | 4321 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { |
| 4497 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT); | 4322 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT); |
| 4498 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT); | 4323 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT); |
| 4499 __ JumpIfSmi(rax, &call_runtime); | 4324 __ JumpIfSmi(rax, &call_runtime); |
| 4500 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8); | 4325 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8); |
| 4501 __ j(above_equal, &call_runtime); | 4326 __ j(above_equal, &call_runtime); |
| (...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5488 | 5313 |
| 5489 | 5314 |
| 5490 void StringCompareStub::Generate(MacroAssembler* masm) { | 5315 void StringCompareStub::Generate(MacroAssembler* masm) { |
| 5491 Label runtime; | 5316 Label runtime; |
| 5492 | 5317 |
| 5493 // Stack frame on entry. | 5318 // Stack frame on entry. |
| 5494 // rsp[0] : return address | 5319 // rsp[0] : return address |
| 5495 // rsp[8] : right string | 5320 // rsp[8] : right string |
| 5496 // rsp[16] : left string | 5321 // rsp[16] : left string |
| 5497 | 5322 |
| 5498 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left | 5323 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 5499 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right | 5324 __ movq(rdx, args.GetArgumentOperand(0)); // left |
| 5325 __ movq(rax, args.GetArgumentOperand(1)); // right |
| 5500 | 5326 |
| 5501 // Check for identity. | 5327 // Check for identity. |
| 5502 Label not_same; | 5328 Label not_same; |
| 5503 __ cmpq(rdx, rax); | 5329 __ cmpq(rdx, rax); |
| 5504 __ j(not_equal, ¬_same, Label::kNear); | 5330 __ j(not_equal, ¬_same, Label::kNear); |
| 5505 __ Move(rax, Smi::FromInt(EQUAL)); | 5331 __ Move(rax, Smi::FromInt(EQUAL)); |
| 5506 Counters* counters = masm->isolate()->counters(); | 5332 Counters* counters = masm->isolate()->counters(); |
| 5507 __ IncrementCounter(counters->string_compare_native(), 1); | 5333 __ IncrementCounter(counters->string_compare_native(), 1); |
| 5508 __ ret(2 * kPointerSize); | 5334 __ ret(2 * kPointerSize); |
| 5509 | 5335 |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6002 | 5828 |
| 6003 __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset)); | 5829 __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset)); |
| 6004 __ decl(scratch); | 5830 __ decl(scratch); |
| 6005 __ push(scratch); | 5831 __ push(scratch); |
| 6006 | 5832 |
| 6007 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 5833 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
| 6008 // not equal to the name and kProbes-th slot is not used (its name is the | 5834 // not equal to the name and kProbes-th slot is not used (its name is the |
| 6009 // undefined value), it guarantees the hash table doesn't contain the | 5835 // undefined value), it guarantees the hash table doesn't contain the |
| 6010 // property. It's true even if some slots represent deleted properties | 5836 // property. It's true even if some slots represent deleted properties |
| 6011 // (their names are the null value). | 5837 // (their names are the null value). |
| 5838 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER, |
| 5839 kPointerSize); |
| 6012 for (int i = kInlinedProbes; i < kTotalProbes; i++) { | 5840 for (int i = kInlinedProbes; i < kTotalProbes; i++) { |
| 6013 // Compute the masked index: (hash + i + i * i) & mask. | 5841 // Compute the masked index: (hash + i + i * i) & mask. |
| 6014 __ movq(scratch, Operand(rsp, 2 * kPointerSize)); | 5842 __ movq(scratch, args.GetArgumentOperand(1)); |
| 6015 if (i > 0) { | 5843 if (i > 0) { |
| 6016 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); | 5844 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); |
| 6017 } | 5845 } |
| 6018 __ and_(scratch, Operand(rsp, 0)); | 5846 __ and_(scratch, Operand(rsp, 0)); |
| 6019 | 5847 |
| 6020 // Scale the index by multiplying by the entry size. | 5848 // Scale the index by multiplying by the entry size. |
| 6021 ASSERT(NameDictionary::kEntrySize == 3); | 5849 ASSERT(NameDictionary::kEntrySize == 3); |
| 6022 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. | 5850 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. |
| 6023 | 5851 |
| 6024 // Having undefined at this place means the name is not contained. | 5852 // Having undefined at this place means the name is not contained. |
| 6025 __ movq(scratch, Operand(dictionary_, | 5853 __ movq(scratch, Operand(dictionary_, |
| 6026 index_, | 5854 index_, |
| 6027 times_pointer_size, | 5855 times_pointer_size, |
| 6028 kElementsStartOffset - kHeapObjectTag)); | 5856 kElementsStartOffset - kHeapObjectTag)); |
| 6029 | 5857 |
| 6030 __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); | 5858 __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); |
| 6031 __ j(equal, ¬_in_dictionary); | 5859 __ j(equal, ¬_in_dictionary); |
| 6032 | 5860 |
| 6033 // Stop if found the property. | 5861 // Stop if found the property. |
| 6034 __ cmpq(scratch, Operand(rsp, 3 * kPointerSize)); | 5862 __ cmpq(scratch, args.GetArgumentOperand(0)); |
| 6035 __ j(equal, &in_dictionary); | 5863 __ j(equal, &in_dictionary); |
| 6036 | 5864 |
| 6037 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { | 5865 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { |
| 6038 // If we hit a key that is not a unique name during negative | 5866 // If we hit a key that is not a unique name during negative |
| 6039 // lookup we have to bailout as this key might be equal to the | 5867 // lookup we have to bailout as this key might be equal to the |
| 6040 // key we are looking for. | 5868 // key we are looking for. |
| 6041 | 5869 |
| 6042 // Check if the entry name is not a unique name. | 5870 // Check if the entry name is not a unique name. |
| 6043 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 5871 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 6044 __ JumpIfNotUniqueName(FieldOperand(scratch, Map::kInstanceTypeOffset), | 5872 __ JumpIfNotUniqueName(FieldOperand(scratch, Map::kInstanceTypeOffset), |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6376 // clobbers rbx, rdx, rdi | 6204 // clobbers rbx, rdx, rdi |
| 6377 // ----------------------------------- | 6205 // ----------------------------------- |
| 6378 | 6206 |
| 6379 Label element_done; | 6207 Label element_done; |
| 6380 Label double_elements; | 6208 Label double_elements; |
| 6381 Label smi_element; | 6209 Label smi_element; |
| 6382 Label slow_elements; | 6210 Label slow_elements; |
| 6383 Label fast_elements; | 6211 Label fast_elements; |
| 6384 | 6212 |
| 6385 // Get array literal index, array literal and its map. | 6213 // Get array literal index, array literal and its map. |
| 6386 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); | 6214 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 6387 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); | 6215 __ movq(rdx, args.GetArgumentOperand(1)); |
| 6216 __ movq(rbx, args.GetArgumentOperand(0)); |
| 6388 __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset)); | 6217 __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset)); |
| 6389 | 6218 |
| 6390 __ CheckFastElements(rdi, &double_elements); | 6219 __ CheckFastElements(rdi, &double_elements); |
| 6391 | 6220 |
| 6392 // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS | 6221 // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS |
| 6393 __ JumpIfSmi(rax, &smi_element); | 6222 __ JumpIfSmi(rax, &smi_element); |
| 6394 __ CheckFastSmiElements(rdi, &fast_elements); | 6223 __ CheckFastSmiElements(rdi, &fast_elements); |
| 6395 | 6224 |
| 6396 // Store into the array literal requires a elements transition. Call into | 6225 // Store into the array literal requires a elements transition. Call into |
| 6397 // the runtime. | 6226 // the runtime. |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6544 Handle<Object> undefined_sentinel( | 6373 Handle<Object> undefined_sentinel( |
| 6545 masm->isolate()->heap()->undefined_value(), | 6374 masm->isolate()->heap()->undefined_value(), |
| 6546 masm->isolate()); | 6375 masm->isolate()); |
| 6547 | 6376 |
| 6548 // is the low bit set? If so, we are holey and that is good. | 6377 // is the low bit set? If so, we are holey and that is good. |
| 6549 __ testb(rdx, Immediate(1)); | 6378 __ testb(rdx, Immediate(1)); |
| 6550 Label normal_sequence; | 6379 Label normal_sequence; |
| 6551 __ j(not_zero, &normal_sequence); | 6380 __ j(not_zero, &normal_sequence); |
| 6552 | 6381 |
| 6553 // look at the first argument | 6382 // look at the first argument |
| 6554 __ movq(rcx, Operand(rsp, kPointerSize)); | 6383 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 6384 __ movq(rcx, args.GetArgumentOperand(0)); |
| 6555 __ testq(rcx, rcx); | 6385 __ testq(rcx, rcx); |
| 6556 __ j(zero, &normal_sequence); | 6386 __ j(zero, &normal_sequence); |
| 6557 | 6387 |
| 6558 // We are going to create a holey array, but our kind is non-holey. | 6388 // We are going to create a holey array, but our kind is non-holey. |
| 6559 // Fix kind and retry (only if we have an allocation site in the cell). | 6389 // Fix kind and retry (only if we have an allocation site in the cell). |
| 6560 __ incl(rdx); | 6390 __ incl(rdx); |
| 6561 __ Cmp(rbx, undefined_sentinel); | 6391 __ Cmp(rbx, undefined_sentinel); |
| 6562 __ j(equal, &normal_sequence); | 6392 __ j(equal, &normal_sequence); |
| 6563 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); | 6393 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); |
| 6564 Handle<Map> allocation_site_map( | 6394 Handle<Map> allocation_site_map( |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6723 InternalArrayNoArgumentConstructorStub stub0(kind); | 6553 InternalArrayNoArgumentConstructorStub stub0(kind); |
| 6724 __ TailCallStub(&stub0); | 6554 __ TailCallStub(&stub0); |
| 6725 | 6555 |
| 6726 __ bind(¬_zero_case); | 6556 __ bind(¬_zero_case); |
| 6727 __ cmpl(rax, Immediate(1)); | 6557 __ cmpl(rax, Immediate(1)); |
| 6728 __ j(greater, ¬_one_case); | 6558 __ j(greater, ¬_one_case); |
| 6729 | 6559 |
| 6730 if (IsFastPackedElementsKind(kind)) { | 6560 if (IsFastPackedElementsKind(kind)) { |
| 6731 // We might need to create a holey array | 6561 // We might need to create a holey array |
| 6732 // look at the first argument | 6562 // look at the first argument |
| 6733 __ movq(rcx, Operand(rsp, kPointerSize)); | 6563 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 6564 __ movq(rcx, args.GetArgumentOperand(0)); |
| 6734 __ testq(rcx, rcx); | 6565 __ testq(rcx, rcx); |
| 6735 __ j(zero, &normal_sequence); | 6566 __ j(zero, &normal_sequence); |
| 6736 | 6567 |
| 6737 InternalArraySingleArgumentConstructorStub | 6568 InternalArraySingleArgumentConstructorStub |
| 6738 stub1_holey(GetHoleyElementsKind(kind)); | 6569 stub1_holey(GetHoleyElementsKind(kind)); |
| 6739 __ TailCallStub(&stub1_holey); | 6570 __ TailCallStub(&stub1_holey); |
| 6740 } | 6571 } |
| 6741 | 6572 |
| 6742 __ bind(&normal_sequence); | 6573 __ bind(&normal_sequence); |
| 6743 InternalArraySingleArgumentConstructorStub stub1(kind); | 6574 InternalArraySingleArgumentConstructorStub stub1(kind); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6800 __ bind(&fast_elements_case); | 6631 __ bind(&fast_elements_case); |
| 6801 GenerateCase(masm, FAST_ELEMENTS); | 6632 GenerateCase(masm, FAST_ELEMENTS); |
| 6802 } | 6633 } |
| 6803 | 6634 |
| 6804 | 6635 |
| 6805 #undef __ | 6636 #undef __ |
| 6806 | 6637 |
| 6807 } } // namespace v8::internal | 6638 } } // namespace v8::internal |
| 6808 | 6639 |
| 6809 #endif // V8_TARGET_ARCH_X64 | 6640 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |