| 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 |