OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 STATIC_ASSERT(kNotStringTag != 0); | 297 STATIC_ASSERT(kNotStringTag != 0); |
298 __ testl(scratch, Immediate(kNotStringTag)); | 298 __ testl(scratch, Immediate(kNotStringTag)); |
299 __ j(not_zero, non_string_object); | 299 __ j(not_zero, non_string_object); |
300 } | 300 } |
301 | 301 |
302 | 302 |
303 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 303 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, |
304 Register receiver, | 304 Register receiver, |
305 Register scratch1, | 305 Register scratch1, |
306 Register scratch2, | 306 Register scratch2, |
307 Label* miss) { | 307 Label* miss, |
| 308 bool support_wrappers) { |
308 Label check_wrapper; | 309 Label check_wrapper; |
309 | 310 |
310 // Check if the object is a string leaving the instance type in the | 311 // Check if the object is a string leaving the instance type in the |
311 // scratch register. | 312 // scratch register. |
312 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); | 313 GenerateStringCheck(masm, receiver, scratch1, miss, |
| 314 support_wrappers ? &check_wrapper : miss); |
313 | 315 |
314 // Load length directly from the string. | 316 // Load length directly from the string. |
315 __ movq(rax, FieldOperand(receiver, String::kLengthOffset)); | 317 __ movq(rax, FieldOperand(receiver, String::kLengthOffset)); |
316 __ ret(0); | 318 __ ret(0); |
317 | 319 |
318 // Check if the object is a JSValue wrapper. | 320 if (support_wrappers) { |
319 __ bind(&check_wrapper); | 321 // Check if the object is a JSValue wrapper. |
320 __ cmpl(scratch1, Immediate(JS_VALUE_TYPE)); | 322 __ bind(&check_wrapper); |
321 __ j(not_equal, miss); | 323 __ cmpl(scratch1, Immediate(JS_VALUE_TYPE)); |
| 324 __ j(not_equal, miss); |
322 | 325 |
323 // Check if the wrapped value is a string and load the length | 326 // Check if the wrapped value is a string and load the length |
324 // directly if it is. | 327 // directly if it is. |
325 __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); | 328 __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
326 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); | 329 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
327 __ movq(rax, FieldOperand(scratch2, String::kLengthOffset)); | 330 __ movq(rax, FieldOperand(scratch2, String::kLengthOffset)); |
328 __ ret(0); | 331 __ ret(0); |
| 332 } |
329 } | 333 } |
330 | 334 |
331 | 335 |
332 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 336 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, |
333 Register receiver, | 337 Register receiver, |
334 Register result, | 338 Register result, |
335 Register scratch, | 339 Register scratch, |
336 Label* miss_label) { | 340 Label* miss_label) { |
337 __ TryGetFunctionPrototype(receiver, result, miss_label); | 341 __ TryGetFunctionPrototype(receiver, result, miss_label); |
338 if (!result.is(rax)) __ movq(rax, result); | 342 if (!result.is(rax)) __ movq(rax, result); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 __ movq(scratch, StackOperandForReturnAddress(0)); | 440 __ movq(scratch, StackOperandForReturnAddress(0)); |
437 __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize), | 441 __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize), |
438 scratch); | 442 scratch); |
439 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); | 443 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); |
440 } | 444 } |
441 | 445 |
442 | 446 |
443 // Generates call to API function. | 447 // Generates call to API function. |
444 static void GenerateFastApiCall(MacroAssembler* masm, | 448 static void GenerateFastApiCall(MacroAssembler* masm, |
445 const CallOptimization& optimization, | 449 const CallOptimization& optimization, |
446 int argc, | 450 int argc) { |
447 bool restore_context) { | |
448 // ----------- S t a t e ------------- | 451 // ----------- S t a t e ------------- |
449 // -- rsp[0] : return address | 452 // -- rsp[0] : return address |
450 // -- rsp[8] : context save | 453 // -- rsp[8] : object passing the type check |
451 // -- rsp[16] : object passing the type check | |
452 // (last fast api call extra argument, | 454 // (last fast api call extra argument, |
453 // set by CheckPrototypes) | 455 // set by CheckPrototypes) |
454 // -- rsp[24] : api function | 456 // -- rsp[16] : api function |
455 // (first fast api call extra argument) | 457 // (first fast api call extra argument) |
456 // -- rsp[32] : api call data | 458 // -- rsp[24] : api call data |
457 // -- rsp[40] : isolate | 459 // -- rsp[32] : isolate |
458 // -- rsp[48] : ReturnValue default value | 460 // -- rsp[40] : ReturnValue default value |
459 // -- rsp[56] : ReturnValue | 461 // -- rsp[48] : ReturnValue |
460 // | 462 // |
461 // -- rsp[64] : last argument | 463 // -- rsp[56] : last argument |
462 // -- ... | 464 // -- ... |
463 // -- rsp[(argc + 7) * 8] : first argument | 465 // -- rsp[(argc + 6) * 8] : first argument |
464 // -- rsp[(argc + 8) * 8] : receiver | 466 // -- rsp[(argc + 7) * 8] : receiver |
465 // ----------------------------------- | 467 // ----------------------------------- |
466 int api_call_argc = argc + kFastApiCallArguments; | |
467 StackArgumentsAccessor args(rsp, api_call_argc); | |
468 | |
469 // Save calling context. | |
470 __ movq(args.GetArgumentOperand(api_call_argc), rsi); | |
471 | |
472 // Get the function and setup the context. | 468 // Get the function and setup the context. |
473 Handle<JSFunction> function = optimization.constant_function(); | 469 Handle<JSFunction> function = optimization.constant_function(); |
474 __ LoadHeapObject(rdi, function); | 470 __ LoadHeapObject(rdi, function); |
475 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 471 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 472 |
| 473 int api_call_argc = argc + kFastApiCallArguments; |
| 474 StackArgumentsAccessor args(rsp, api_call_argc); |
| 475 |
476 // Pass the additional arguments. | 476 // Pass the additional arguments. |
477 __ movq(args.GetArgumentOperand(api_call_argc - 2), rdi); | 477 __ movq(args.GetArgumentOperand(api_call_argc - 1), rdi); |
478 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 478 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
479 Handle<Object> call_data(api_call_info->data(), masm->isolate()); | 479 Handle<Object> call_data(api_call_info->data(), masm->isolate()); |
480 if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 480 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
481 __ Move(rcx, api_call_info); | 481 __ Move(rcx, api_call_info); |
482 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); | 482 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); |
483 __ movq(args.GetArgumentOperand(api_call_argc - 3), rbx); | 483 __ movq(args.GetArgumentOperand(api_call_argc - 2), rbx); |
484 } else { | 484 } else { |
485 __ Move(args.GetArgumentOperand(api_call_argc - 3), call_data); | 485 __ Move(args.GetArgumentOperand(api_call_argc - 2), call_data); |
486 } | 486 } |
487 __ movq(kScratchRegister, | 487 __ movq(kScratchRegister, |
488 ExternalReference::isolate_address(masm->isolate())); | 488 ExternalReference::isolate_address(masm->isolate())); |
| 489 __ movq(args.GetArgumentOperand(api_call_argc - 3), kScratchRegister); |
| 490 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); |
489 __ movq(args.GetArgumentOperand(api_call_argc - 4), kScratchRegister); | 491 __ movq(args.GetArgumentOperand(api_call_argc - 4), kScratchRegister); |
490 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | |
491 __ movq(args.GetArgumentOperand(api_call_argc - 5), kScratchRegister); | 492 __ movq(args.GetArgumentOperand(api_call_argc - 5), kScratchRegister); |
492 __ movq(args.GetArgumentOperand(api_call_argc - 6), kScratchRegister); | |
493 | 493 |
494 // Prepare arguments. | 494 // Prepare arguments. |
495 STATIC_ASSERT(kFastApiCallArguments == 7); | 495 STATIC_ASSERT(kFastApiCallArguments == 6); |
496 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); | 496 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); |
497 | 497 |
498 // Function address is a foreign pointer outside V8's heap. | 498 // Function address is a foreign pointer outside V8's heap. |
499 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 499 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
500 | 500 |
| 501 #if defined(__MINGW64__) || defined(_WIN64) |
| 502 Register arguments_arg = rcx; |
| 503 Register callback_arg = rdx; |
| 504 #else |
| 505 Register arguments_arg = rdi; |
| 506 Register callback_arg = rsi; |
| 507 #endif |
| 508 |
501 // Allocate the v8::Arguments structure in the arguments' space since | 509 // Allocate the v8::Arguments structure in the arguments' space since |
502 // it's not controlled by GC. | 510 // it's not controlled by GC. |
503 const int kApiStackSpace = 4; | 511 const int kApiStackSpace = 4; |
504 | 512 |
505 __ PrepareCallApiFunction(kApiStackSpace); | 513 __ PrepareCallApiFunction(kApiStackSpace); |
506 | 514 |
507 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. | 515 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. |
508 __ addq(rbx, Immediate(argc * kPointerSize)); | 516 __ addq(rbx, Immediate(argc * kPointerSize)); |
509 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. | 517 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. |
510 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. | 518 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. |
511 // v8::Arguments::is_construct_call_. | 519 // v8::Arguments::is_construct_call_. |
512 __ Set(StackSpaceOperand(3), 0); | 520 __ Set(StackSpaceOperand(3), 0); |
513 | 521 |
514 #if defined(__MINGW64__) || defined(_WIN64) | |
515 Register arguments_arg = rcx; | |
516 Register callback_arg = rdx; | |
517 #else | |
518 Register arguments_arg = rdi; | |
519 Register callback_arg = rsi; | |
520 #endif | |
521 | |
522 // v8::InvocationCallback's argument. | 522 // v8::InvocationCallback's argument. |
523 __ lea(arguments_arg, StackSpaceOperand(0)); | 523 __ lea(arguments_arg, StackSpaceOperand(0)); |
524 | 524 |
525 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); | 525 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
526 | 526 |
527 Operand context_restore_operand(rbp, 2 * kPointerSize); | |
528 Operand return_value_operand( | |
529 rbp, (kFastApiCallArguments + 1) * kPointerSize); | |
530 __ CallApiFunctionAndReturn(function_address, | 527 __ CallApiFunctionAndReturn(function_address, |
531 thunk_address, | 528 thunk_address, |
532 callback_arg, | 529 callback_arg, |
533 api_call_argc + 1, | 530 api_call_argc + 1, |
534 return_value_operand, | 531 kFastApiCallArguments + 1); |
535 restore_context ? | |
536 &context_restore_operand : NULL); | |
537 } | 532 } |
538 | 533 |
539 | 534 |
540 // Generate call to api function. | 535 // Generate call to api function. |
541 static void GenerateFastApiCall(MacroAssembler* masm, | 536 static void GenerateFastApiCall(MacroAssembler* masm, |
542 const CallOptimization& optimization, | 537 const CallOptimization& optimization, |
543 Register receiver, | 538 Register receiver, |
544 Register scratch, | 539 Register scratch, |
545 int argc, | 540 int argc, |
546 Register* values) { | 541 Register* values) { |
547 ASSERT(optimization.is_simple_api_call()); | 542 ASSERT(optimization.is_simple_api_call()); |
548 ASSERT(!receiver.is(scratch)); | 543 ASSERT(!receiver.is(scratch)); |
549 | 544 |
550 const int stack_space = kFastApiCallArguments + argc + 1; | 545 const int stack_space = kFastApiCallArguments + argc + 1; |
551 const int kHolderIndex = kFastApiCallArguments + | |
552 FunctionCallbackArguments::kHolderIndex; | |
553 // Copy return value. | 546 // Copy return value. |
554 __ movq(scratch, Operand(rsp, 0)); | 547 __ movq(scratch, Operand(rsp, 0)); |
555 // Assign stack space for the call arguments. | 548 // Assign stack space for the call arguments. |
556 __ subq(rsp, Immediate(stack_space * kPointerSize)); | 549 __ subq(rsp, Immediate(stack_space * kPointerSize)); |
557 // Move the return address on top of the stack. | 550 // Move the return address on top of the stack. |
558 __ movq(Operand(rsp, 0), scratch); | 551 __ movq(Operand(rsp, 0), scratch); |
559 // Write holder to stack frame. | 552 // Write holder to stack frame. |
560 __ movq(Operand(rsp, kHolderIndex * kPointerSize), receiver); | 553 __ movq(Operand(rsp, 1 * kPointerSize), receiver); |
561 // Write receiver to stack frame. | 554 // Write receiver to stack frame. |
562 int index = stack_space; | 555 int index = stack_space; |
563 __ movq(Operand(rsp, index-- * kPointerSize), receiver); | 556 __ movq(Operand(rsp, index-- * kPointerSize), receiver); |
564 // Write the arguments to stack frame. | 557 // Write the arguments to stack frame. |
565 for (int i = 0; i < argc; i++) { | 558 for (int i = 0; i < argc; i++) { |
566 ASSERT(!receiver.is(values[i])); | 559 ASSERT(!receiver.is(values[i])); |
567 ASSERT(!scratch.is(values[i])); | 560 ASSERT(!scratch.is(values[i])); |
568 __ movq(Operand(rsp, index-- * kPointerSize), values[i]); | 561 __ movq(Operand(rsp, index-- * kPointerSize), values[i]); |
569 } | 562 } |
570 | 563 |
571 GenerateFastApiCall(masm, optimization, argc, true); | 564 GenerateFastApiCall(masm, optimization, argc); |
572 } | 565 } |
573 | 566 |
574 | 567 |
575 class CallInterceptorCompiler BASE_EMBEDDED { | 568 class CallInterceptorCompiler BASE_EMBEDDED { |
576 public: | 569 public: |
577 CallInterceptorCompiler(StubCompiler* stub_compiler, | 570 CallInterceptorCompiler(StubCompiler* stub_compiler, |
578 const ParameterCount& arguments, | 571 const ParameterCount& arguments, |
579 Register name, | 572 Register name, |
580 Code::ExtraICState extra_ic_state) | 573 Code::ExtraICState extra_ic_state) |
581 : stub_compiler_(stub_compiler), | 574 : stub_compiler_(stub_compiler), |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 } else { | 668 } else { |
676 // CheckPrototypes has a side effect of fetching a 'holder' | 669 // CheckPrototypes has a side effect of fetching a 'holder' |
677 // for API (object which is instanceof for the signature). It's | 670 // for API (object which is instanceof for the signature). It's |
678 // safe to omit it here, as if present, it should be fetched | 671 // safe to omit it here, as if present, it should be fetched |
679 // by the previous CheckPrototypes. | 672 // by the previous CheckPrototypes. |
680 ASSERT(depth2 == kInvalidProtoDepth); | 673 ASSERT(depth2 == kInvalidProtoDepth); |
681 } | 674 } |
682 | 675 |
683 // Invoke function. | 676 // Invoke function. |
684 if (can_do_fast_api_call) { | 677 if (can_do_fast_api_call) { |
685 GenerateFastApiCall(masm, optimization, arguments_.immediate(), false); | 678 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
686 } else { | 679 } else { |
687 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 680 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
688 ? CALL_AS_FUNCTION | 681 ? CALL_AS_FUNCTION |
689 : CALL_AS_METHOD; | 682 : CALL_AS_METHOD; |
690 Handle<JSFunction> fun = optimization.constant_function(); | 683 Handle<JSFunction> fun = optimization.constant_function(); |
691 ParameterCount expected(fun); | 684 ParameterCount expected(fun); |
692 __ InvokeFunction(fun, expected, arguments_, | 685 __ InvokeFunction(fun, expected, arguments_, |
693 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 686 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
694 } | 687 } |
695 | 688 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 } else if (FLAG_track_fields && representation.IsSmi()) { | 835 } else if (FLAG_track_fields && representation.IsSmi()) { |
843 __ JumpIfNotSmi(value_reg, miss_label); | 836 __ JumpIfNotSmi(value_reg, miss_label); |
844 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 837 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
845 __ JumpIfSmi(value_reg, miss_label); | 838 __ JumpIfSmi(value_reg, miss_label); |
846 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 839 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
847 Label do_store, heap_number; | 840 Label do_store, heap_number; |
848 __ AllocateHeapNumber(storage_reg, scratch1, slow); | 841 __ AllocateHeapNumber(storage_reg, scratch1, slow); |
849 | 842 |
850 __ JumpIfNotSmi(value_reg, &heap_number); | 843 __ JumpIfNotSmi(value_reg, &heap_number); |
851 __ SmiToInteger32(scratch1, value_reg); | 844 __ SmiToInteger32(scratch1, value_reg); |
852 __ Cvtlsi2sd(xmm0, scratch1); | 845 __ cvtlsi2sd(xmm0, scratch1); |
853 __ jmp(&do_store); | 846 __ jmp(&do_store); |
854 | 847 |
855 __ bind(&heap_number); | 848 __ bind(&heap_number); |
856 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 849 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
857 miss_label, DONT_DO_SMI_CHECK); | 850 miss_label, DONT_DO_SMI_CHECK); |
858 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 851 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
859 | 852 |
860 __ bind(&do_store); | 853 __ bind(&do_store); |
861 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 854 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
862 } | 855 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 __ movq(scratch1, | 989 __ movq(scratch1, |
997 FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 990 FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
998 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 991 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
999 __ movq(scratch1, FieldOperand(scratch1, offset)); | 992 __ movq(scratch1, FieldOperand(scratch1, offset)); |
1000 } | 993 } |
1001 | 994 |
1002 // Store the value into the storage. | 995 // Store the value into the storage. |
1003 Label do_store, heap_number; | 996 Label do_store, heap_number; |
1004 __ JumpIfNotSmi(value_reg, &heap_number); | 997 __ JumpIfNotSmi(value_reg, &heap_number); |
1005 __ SmiToInteger32(scratch2, value_reg); | 998 __ SmiToInteger32(scratch2, value_reg); |
1006 __ Cvtlsi2sd(xmm0, scratch2); | 999 __ cvtlsi2sd(xmm0, scratch2); |
1007 __ jmp(&do_store); | 1000 __ jmp(&do_store); |
1008 | 1001 |
1009 __ bind(&heap_number); | 1002 __ bind(&heap_number); |
1010 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 1003 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
1011 miss_label, DONT_DO_SMI_CHECK); | 1004 miss_label, DONT_DO_SMI_CHECK); |
1012 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 1005 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
1013 __ bind(&do_store); | 1006 __ bind(&do_store); |
1014 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); | 1007 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); |
1015 // Return the value (register rax). | 1008 // Return the value (register rax). |
1016 ASSERT(value_reg.is(rax)); | 1009 ASSERT(value_reg.is(rax)); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1084 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
1092 Register object_reg, | 1085 Register object_reg, |
1093 Handle<JSObject> holder, | 1086 Handle<JSObject> holder, |
1094 Register holder_reg, | 1087 Register holder_reg, |
1095 Register scratch1, | 1088 Register scratch1, |
1096 Register scratch2, | 1089 Register scratch2, |
1097 Handle<Name> name, | 1090 Handle<Name> name, |
1098 int save_at_depth, | 1091 int save_at_depth, |
1099 Label* miss, | 1092 Label* miss, |
1100 PrototypeCheckType check) { | 1093 PrototypeCheckType check) { |
1101 const int kHolderIndex = kFastApiCallArguments + | |
1102 FunctionCallbackArguments::kHolderIndex; | |
1103 // Make sure that the type feedback oracle harvests the receiver map. | 1094 // Make sure that the type feedback oracle harvests the receiver map. |
1104 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1095 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
1105 __ Move(scratch1, Handle<Map>(object->map())); | 1096 __ Move(scratch1, Handle<Map>(object->map())); |
1106 | 1097 |
1107 Handle<JSObject> first = object; | 1098 Handle<JSObject> first = object; |
1108 // Make sure there's no overlap between holder and object registers. | 1099 // Make sure there's no overlap between holder and object registers. |
1109 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1100 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
1110 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1101 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
1111 && !scratch2.is(scratch1)); | 1102 && !scratch2.is(scratch1)); |
1112 | 1103 |
1113 // Keep track of the current object in register reg. On the first | 1104 // Keep track of the current object in register reg. On the first |
1114 // iteration, reg is an alias for object_reg, on later iterations, | 1105 // iteration, reg is an alias for object_reg, on later iterations, |
1115 // it is an alias for holder_reg. | 1106 // it is an alias for holder_reg. |
1116 Register reg = object_reg; | 1107 Register reg = object_reg; |
1117 int depth = 0; | 1108 int depth = 0; |
1118 | 1109 |
1119 if (save_at_depth == depth) { | 1110 if (save_at_depth == depth) { |
1120 __ movq(Operand(rsp, kHolderIndex * kPointerSize), object_reg); | 1111 __ movq(Operand(rsp, kPCOnStackSize), object_reg); |
1121 } | 1112 } |
1122 | 1113 |
1123 // Check the maps in the prototype chain. | 1114 // Check the maps in the prototype chain. |
1124 // Traverse the prototype chain from the object and do map checks. | 1115 // Traverse the prototype chain from the object and do map checks. |
1125 Handle<JSObject> current = object; | 1116 Handle<JSObject> current = object; |
1126 while (!current.is_identical_to(holder)) { | 1117 while (!current.is_identical_to(holder)) { |
1127 ++depth; | 1118 ++depth; |
1128 | 1119 |
1129 // Only global objects and objects that do not require access | 1120 // Only global objects and objects that do not require access |
1130 // checks are allowed in stubs. | 1121 // checks are allowed in stubs. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1170 // The prototype is in new space; we cannot store a reference to it | 1161 // The prototype is in new space; we cannot store a reference to it |
1171 // in the code. Load it from the map. | 1162 // in the code. Load it from the map. |
1172 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1163 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
1173 } else { | 1164 } else { |
1174 // The prototype is in old space; load it directly. | 1165 // The prototype is in old space; load it directly. |
1175 __ Move(reg, prototype); | 1166 __ Move(reg, prototype); |
1176 } | 1167 } |
1177 } | 1168 } |
1178 | 1169 |
1179 if (save_at_depth == depth) { | 1170 if (save_at_depth == depth) { |
1180 __ movq(Operand(rsp, kHolderIndex * kPointerSize), reg); | 1171 __ movq(Operand(rsp, kPCOnStackSize), reg); |
1181 } | 1172 } |
1182 | 1173 |
1183 // Go to the next object in the prototype chain. | 1174 // Go to the next object in the prototype chain. |
1184 current = prototype; | 1175 current = prototype; |
1185 } | 1176 } |
1186 ASSERT(current.is_identical_to(holder)); | 1177 ASSERT(current.is_identical_to(holder)); |
1187 | 1178 |
1188 // Log the check depth. | 1179 // Log the check depth. |
1189 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1180 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
1190 | 1181 |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 // The context register (rsi) has been saved in PrepareCallApiFunction and | 1383 // The context register (rsi) has been saved in PrepareCallApiFunction and |
1393 // could be used to pass arguments. | 1384 // could be used to pass arguments. |
1394 __ lea(accessor_info_arg, StackSpaceOperand(0)); | 1385 __ lea(accessor_info_arg, StackSpaceOperand(0)); |
1395 | 1386 |
1396 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1387 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
1397 | 1388 |
1398 __ CallApiFunctionAndReturn(getter_address, | 1389 __ CallApiFunctionAndReturn(getter_address, |
1399 thunk_address, | 1390 thunk_address, |
1400 getter_arg, | 1391 getter_arg, |
1401 kStackSpace, | 1392 kStackSpace, |
1402 Operand(rbp, 6 * kPointerSize), | 1393 6); |
1403 NULL); | |
1404 } | 1394 } |
1405 | 1395 |
1406 | 1396 |
1407 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1397 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
1408 // Return the constant value. | 1398 // Return the constant value. |
1409 __ LoadObject(rax, value); | 1399 __ LoadObject(rax, value); |
1410 __ ret(0); | 1400 __ ret(0); |
1411 } | 1401 } |
1412 | 1402 |
1413 | 1403 |
(...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2511 | 2501 |
2512 // Check that the maps haven't changed and find a Holder as a side effect. | 2502 // Check that the maps haven't changed and find a Holder as a side effect. |
2513 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2503 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
2514 name, depth, &miss); | 2504 name, depth, &miss); |
2515 | 2505 |
2516 // Move the return address on top of the stack. | 2506 // Move the return address on top of the stack. |
2517 __ movq(rax, | 2507 __ movq(rax, |
2518 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); | 2508 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); |
2519 __ movq(StackOperandForReturnAddress(0), rax); | 2509 __ movq(StackOperandForReturnAddress(0), rax); |
2520 | 2510 |
2521 GenerateFastApiCall(masm(), optimization, argc, false); | 2511 GenerateFastApiCall(masm(), optimization, argc); |
2522 | 2512 |
2523 __ bind(&miss); | 2513 __ bind(&miss); |
2524 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2514 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
2525 | 2515 |
2526 __ bind(&miss_before_stack_reserved); | 2516 __ bind(&miss_before_stack_reserved); |
2527 GenerateMissBranch(); | 2517 GenerateMissBranch(); |
2528 | 2518 |
2529 // Return the generated code. | 2519 // Return the generated code. |
2530 return GetCode(function); | 2520 return GetCode(function); |
2531 } | 2521 } |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3172 // ----------------------------------- | 3162 // ----------------------------------- |
3173 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3163 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3174 } | 3164 } |
3175 | 3165 |
3176 | 3166 |
3177 #undef __ | 3167 #undef __ |
3178 | 3168 |
3179 } } // namespace v8::internal | 3169 } } // namespace v8::internal |
3180 | 3170 |
3181 #endif // V8_TARGET_ARCH_X64 | 3171 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |