| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2381 case Token::SHR: | 2381 case Token::SHR: |
| 2382 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); | 2382 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
| 2383 break; | 2383 break; |
| 2384 default: | 2384 default: |
| 2385 UNREACHABLE(); | 2385 UNREACHABLE(); |
| 2386 } | 2386 } |
| 2387 } | 2387 } |
| 2388 | 2388 |
| 2389 | 2389 |
| 2390 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { | 2390 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
| 2391 NearLabel call_runtime; | 2391 ASSERT(op_ == Token::ADD); |
| 2392 NearLabel left_not_string, call_runtime; |
| 2392 | 2393 |
| 2393 // Registers containing left and right operands respectively. | 2394 // Registers containing left and right operands respectively. |
| 2394 Register left = edx; | 2395 Register left = edx; |
| 2395 Register right = eax; | 2396 Register right = eax; |
| 2396 | 2397 |
| 2397 // Test if left operand is a string. | 2398 // Test if left operand is a string. |
| 2398 NearLabel left_not_string; | |
| 2399 __ test(left, Immediate(kSmiTagMask)); | 2399 __ test(left, Immediate(kSmiTagMask)); |
| 2400 __ j(zero, &left_not_string); | 2400 __ j(zero, &left_not_string); |
| 2401 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 2401 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
| 2402 __ j(above_equal, &left_not_string); | 2402 __ j(above_equal, &left_not_string); |
| 2403 | 2403 |
| 2404 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); | 2404 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
| 2405 GenerateRegisterArgsPush(masm); | 2405 GenerateRegisterArgsPush(masm); |
| 2406 __ TailCallStub(&string_add_left_stub); | 2406 __ TailCallStub(&string_add_left_stub); |
| 2407 | 2407 |
| 2408 // Left operand is not a string, test right. | 2408 // Left operand is not a string, test right. |
| (...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3398 __ cvtsi2sd(xmm3, Operand(ecx)); | 3398 __ cvtsi2sd(xmm3, Operand(ecx)); |
| 3399 | 3399 |
| 3400 Label exponent_nonsmi; | 3400 Label exponent_nonsmi; |
| 3401 Label base_nonsmi; | 3401 Label base_nonsmi; |
| 3402 // If the exponent is a heap number go to that specific case. | 3402 // If the exponent is a heap number go to that specific case. |
| 3403 __ test(eax, Immediate(kSmiTagMask)); | 3403 __ test(eax, Immediate(kSmiTagMask)); |
| 3404 __ j(not_zero, &exponent_nonsmi); | 3404 __ j(not_zero, &exponent_nonsmi); |
| 3405 __ test(edx, Immediate(kSmiTagMask)); | 3405 __ test(edx, Immediate(kSmiTagMask)); |
| 3406 __ j(not_zero, &base_nonsmi); | 3406 __ j(not_zero, &base_nonsmi); |
| 3407 | 3407 |
| 3408 // Optimized version when both exponent and base is a smi. | 3408 // Optimized version when both exponent and base are smis. |
| 3409 Label powi; | 3409 Label powi; |
| 3410 __ SmiUntag(edx); | 3410 __ SmiUntag(edx); |
| 3411 __ cvtsi2sd(xmm0, Operand(edx)); | 3411 __ cvtsi2sd(xmm0, Operand(edx)); |
| 3412 __ jmp(&powi); | 3412 __ jmp(&powi); |
| 3413 // exponent is smi and base is a heapnumber. | 3413 // exponent is smi and base is a heapnumber. |
| 3414 __ bind(&base_nonsmi); | 3414 __ bind(&base_nonsmi); |
| 3415 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3415 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3416 FACTORY->heap_number_map()); | 3416 FACTORY->heap_number_map()); |
| 3417 __ j(not_equal, &call_runtime); | 3417 __ j(not_equal, &call_runtime); |
| 3418 | 3418 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3437 // Load xmm1 with 1. | 3437 // Load xmm1 with 1. |
| 3438 __ movsd(xmm1, xmm3); | 3438 __ movsd(xmm1, xmm3); |
| 3439 NearLabel while_true; | 3439 NearLabel while_true; |
| 3440 NearLabel no_multiply; | 3440 NearLabel no_multiply; |
| 3441 | 3441 |
| 3442 __ bind(&while_true); | 3442 __ bind(&while_true); |
| 3443 __ shr(eax, 1); | 3443 __ shr(eax, 1); |
| 3444 __ j(not_carry, &no_multiply); | 3444 __ j(not_carry, &no_multiply); |
| 3445 __ mulsd(xmm1, xmm0); | 3445 __ mulsd(xmm1, xmm0); |
| 3446 __ bind(&no_multiply); | 3446 __ bind(&no_multiply); |
| 3447 __ test(eax, Operand(eax)); | |
| 3448 __ mulsd(xmm0, xmm0); | 3447 __ mulsd(xmm0, xmm0); |
| 3449 __ j(not_zero, &while_true); | 3448 __ j(not_zero, &while_true); |
| 3450 | 3449 |
| 3451 // base has the original value of the exponent - if the exponent is | 3450 // base has the original value of the exponent - if the exponent is |
| 3452 // negative return 1/result. | 3451 // negative return 1/result. |
| 3453 __ test(edx, Operand(edx)); | 3452 __ test(edx, Operand(edx)); |
| 3454 __ j(positive, &allocate_return); | 3453 __ j(positive, &allocate_return); |
| 3455 // Special case if xmm1 has reached infinity. | 3454 // Special case if xmm1 has reached infinity. |
| 3456 __ mov(ecx, Immediate(0x7FB00000)); | 3455 __ mov(ecx, Immediate(0x7FB00000)); |
| 3457 __ movd(xmm0, Operand(ecx)); | 3456 __ movd(xmm0, Operand(ecx)); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3524 // Calculates square root. | 3523 // Calculates square root. |
| 3525 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | 3524 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
| 3526 __ xorpd(xmm1, xmm1); | 3525 __ xorpd(xmm1, xmm1); |
| 3527 __ addsd(xmm1, xmm0); | 3526 __ addsd(xmm1, xmm0); |
| 3528 __ sqrtsd(xmm1, xmm1); | 3527 __ sqrtsd(xmm1, xmm1); |
| 3529 | 3528 |
| 3530 __ bind(&allocate_return); | 3529 __ bind(&allocate_return); |
| 3531 __ AllocateHeapNumber(ecx, eax, edx, &call_runtime); | 3530 __ AllocateHeapNumber(ecx, eax, edx, &call_runtime); |
| 3532 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm1); | 3531 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm1); |
| 3533 __ mov(eax, ecx); | 3532 __ mov(eax, ecx); |
| 3534 __ ret(2); | 3533 __ ret(2 * kPointerSize); |
| 3535 | 3534 |
| 3536 __ bind(&call_runtime); | 3535 __ bind(&call_runtime); |
| 3537 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | 3536 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
| 3538 } | 3537 } |
| 3539 | 3538 |
| 3540 | 3539 |
| 3541 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 3540 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
| 3542 // The key is in edx and the parameter count is in eax. | 3541 // The key is in edx and the parameter count is in eax. |
| 3543 | 3542 |
| 3544 // The displacement is used for skipping the frame pointer on the | 3543 // The displacement is used for skipping the frame pointer on the |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3885 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | 3884 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
| 3886 __ SmiUntag(ebx); // Previous index from smi. | 3885 __ SmiUntag(ebx); // Previous index from smi. |
| 3887 | 3886 |
| 3888 // eax: subject string | 3887 // eax: subject string |
| 3889 // ebx: previous index | 3888 // ebx: previous index |
| 3890 // edx: code | 3889 // edx: code |
| 3891 // edi: encoding of subject string (1 if ascii 0 if two_byte); | 3890 // edi: encoding of subject string (1 if ascii 0 if two_byte); |
| 3892 // All checks done. Now push arguments for native regexp code. | 3891 // All checks done. Now push arguments for native regexp code. |
| 3893 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1); | 3892 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1); |
| 3894 | 3893 |
| 3895 static const int kRegExpExecuteArguments = 7; | 3894 // Isolates: note we add an additional parameter here (isolate pointer). |
| 3896 __ PrepareCallCFunction(kRegExpExecuteArguments, ecx); | 3895 static const int kRegExpExecuteArguments = 8; |
| 3896 __ EnterApiExitFrame(kRegExpExecuteArguments); |
| 3897 |
| 3898 // Argument 8: Pass current isolate address. |
| 3899 __ mov(Operand(esp, 7 * kPointerSize), |
| 3900 Immediate(ExternalReference::isolate_address())); |
| 3897 | 3901 |
| 3898 // Argument 7: Indicate that this is a direct call from JavaScript. | 3902 // Argument 7: Indicate that this is a direct call from JavaScript. |
| 3899 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); | 3903 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); |
| 3900 | 3904 |
| 3901 // Argument 6: Start (high end) of backtracking stack memory area. | 3905 // Argument 6: Start (high end) of backtracking stack memory area. |
| 3902 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); | 3906 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); |
| 3903 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 3907 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
| 3904 __ mov(Operand(esp, 5 * kPointerSize), ecx); | 3908 __ mov(Operand(esp, 5 * kPointerSize), ecx); |
| 3905 | 3909 |
| 3906 // Argument 5: static offsets vector buffer. | 3910 // Argument 5: static offsets vector buffer. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3931 __ bind(&setup_rest); | 3935 __ bind(&setup_rest); |
| 3932 | 3936 |
| 3933 // Argument 2: Previous index. | 3937 // Argument 2: Previous index. |
| 3934 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 3938 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 3935 | 3939 |
| 3936 // Argument 1: Subject string. | 3940 // Argument 1: Subject string. |
| 3937 __ mov(Operand(esp, 0 * kPointerSize), eax); | 3941 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 3938 | 3942 |
| 3939 // Locate the code entry and call it. | 3943 // Locate the code entry and call it. |
| 3940 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); | 3944 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 3941 __ CallCFunction(edx, kRegExpExecuteArguments); | 3945 __ call(Operand(edx)); |
| 3946 |
| 3947 // Drop arguments and come back to JS mode. |
| 3948 __ LeaveApiExitFrame(); |
| 3942 | 3949 |
| 3943 // Check the result. | 3950 // Check the result. |
| 3944 Label success; | 3951 Label success; |
| 3945 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS); | 3952 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS); |
| 3946 __ j(equal, &success, taken); | 3953 __ j(equal, &success, taken); |
| 3947 Label failure; | 3954 Label failure; |
| 3948 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); | 3955 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); |
| 3949 __ j(equal, &failure, taken); | 3956 __ j(equal, &failure, taken); |
| 3950 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); | 3957 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); |
| 3951 // If not exception it can only be retry. Handle that in the runtime system. | 3958 // If not exception it can only be retry. Handle that in the runtime system. |
| 3952 __ j(not_equal, &runtime); | 3959 __ j(not_equal, &runtime); |
| 3953 // Result must now be exception. If there is no pending exception already a | 3960 // Result must now be exception. If there is no pending exception already a |
| 3954 // stack overflow (on the backtrack stack) was detected in RegExp code but | 3961 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 3955 // haven't created the exception yet. Handle that in the runtime system. | 3962 // haven't created the exception yet. Handle that in the runtime system. |
| 3956 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 3963 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 3957 ExternalReference pending_exception(Isolate::k_pending_exception_address); | 3964 ExternalReference pending_exception(Isolate::k_pending_exception_address); |
| 3958 __ mov(eax, | 3965 __ mov(edx, |
| 3959 Operand::StaticVariable(ExternalReference::the_hole_value_location())); | 3966 Operand::StaticVariable(ExternalReference::the_hole_value_location())); |
| 3960 __ cmp(eax, Operand::StaticVariable(pending_exception)); | 3967 __ mov(eax, Operand::StaticVariable(pending_exception)); |
| 3968 __ cmp(edx, Operand(eax)); |
| 3961 __ j(equal, &runtime); | 3969 __ j(equal, &runtime); |
| 3970 // For exception, throw the exception again. |
| 3971 |
| 3972 // Clear the pending exception variable. |
| 3973 __ mov(Operand::StaticVariable(pending_exception), edx); |
| 3974 |
| 3975 // Special handling of termination exceptions which are uncatchable |
| 3976 // by javascript code. |
| 3977 __ cmp(eax, FACTORY->termination_exception()); |
| 3978 Label throw_termination_exception; |
| 3979 __ j(equal, &throw_termination_exception); |
| 3980 |
| 3981 // Handle normal exception by following handler chain. |
| 3982 __ Throw(eax); |
| 3983 |
| 3984 __ bind(&throw_termination_exception); |
| 3985 __ ThrowUncatchable(TERMINATION, eax); |
| 3986 |
| 3962 __ bind(&failure); | 3987 __ bind(&failure); |
| 3963 // For failure and exception return null. | 3988 // For failure to match, return null. |
| 3964 __ mov(Operand(eax), FACTORY->null_value()); | 3989 __ mov(Operand(eax), FACTORY->null_value()); |
| 3965 __ ret(4 * kPointerSize); | 3990 __ ret(4 * kPointerSize); |
| 3966 | 3991 |
| 3967 // Load RegExp data. | 3992 // Load RegExp data. |
| 3968 __ bind(&success); | 3993 __ bind(&success); |
| 3969 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 3994 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
| 3970 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 3995 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
| 3971 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); | 3996 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 3972 // Calculate number of capture registers (number_of_captures + 1) * 2. | 3997 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 3973 STATIC_ASSERT(kSmiTag == 0); | 3998 STATIC_ASSERT(kSmiTag == 0); |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4628 __ Set(eax, Immediate(argc_)); | 4653 __ Set(eax, Immediate(argc_)); |
| 4629 __ Set(ebx, Immediate(0)); | 4654 __ Set(ebx, Immediate(0)); |
| 4630 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 4655 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
| 4631 Handle<Code> adaptor(Isolate::Current()->builtins()->builtin( | 4656 Handle<Code> adaptor(Isolate::Current()->builtins()->builtin( |
| 4632 Builtins::ArgumentsAdaptorTrampoline)); | 4657 Builtins::ArgumentsAdaptorTrampoline)); |
| 4633 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 4658 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
| 4634 } | 4659 } |
| 4635 | 4660 |
| 4636 | 4661 |
| 4637 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 4662 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 4638 // eax holds the exception. | 4663 __ Throw(eax); |
| 4639 | |
| 4640 // Adjust this code if not the case. | |
| 4641 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
| 4642 | |
| 4643 // Drop the sp to the top of the handler. | |
| 4644 ExternalReference handler_address(Isolate::k_handler_address); | |
| 4645 __ mov(esp, Operand::StaticVariable(handler_address)); | |
| 4646 | |
| 4647 // Restore next handler and frame pointer, discard handler state. | |
| 4648 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 4649 __ pop(Operand::StaticVariable(handler_address)); | |
| 4650 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); | |
| 4651 __ pop(ebp); | |
| 4652 __ pop(edx); // Remove state. | |
| 4653 | |
| 4654 // Before returning we restore the context from the frame pointer if | |
| 4655 // not NULL. The frame pointer is NULL in the exception handler of | |
| 4656 // a JS entry frame. | |
| 4657 __ Set(esi, Immediate(0)); // Tentatively set context pointer to NULL. | |
| 4658 NearLabel skip; | |
| 4659 __ cmp(ebp, 0); | |
| 4660 __ j(equal, &skip, not_taken); | |
| 4661 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 4662 __ bind(&skip); | |
| 4663 | |
| 4664 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 4665 __ ret(0); | |
| 4666 } | 4664 } |
| 4667 | 4665 |
| 4668 | 4666 |
| 4669 void CEntryStub::GenerateCore(MacroAssembler* masm, | 4667 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| 4670 Label* throw_normal_exception, | 4668 Label* throw_normal_exception, |
| 4671 Label* throw_termination_exception, | 4669 Label* throw_termination_exception, |
| 4672 Label* throw_out_of_memory_exception, | 4670 Label* throw_out_of_memory_exception, |
| 4673 bool do_gc, | 4671 bool do_gc, |
| 4674 bool always_allocate_scope) { | 4672 bool always_allocate_scope) { |
| 4675 // eax: result parameter for PerformGC, if any | 4673 // eax: result parameter for PerformGC, if any |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4781 // Handle normal exception. | 4779 // Handle normal exception. |
| 4782 __ jmp(throw_normal_exception); | 4780 __ jmp(throw_normal_exception); |
| 4783 | 4781 |
| 4784 // Retry. | 4782 // Retry. |
| 4785 __ bind(&retry); | 4783 __ bind(&retry); |
| 4786 } | 4784 } |
| 4787 | 4785 |
| 4788 | 4786 |
| 4789 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 4787 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
| 4790 UncatchableExceptionType type) { | 4788 UncatchableExceptionType type) { |
| 4791 // Adjust this code if not the case. | 4789 __ ThrowUncatchable(type, eax); |
| 4792 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
| 4793 | |
| 4794 // Drop sp to the top stack handler. | |
| 4795 ExternalReference handler_address(Isolate::k_handler_address); | |
| 4796 __ mov(esp, Operand::StaticVariable(handler_address)); | |
| 4797 | |
| 4798 // Unwind the handlers until the ENTRY handler is found. | |
| 4799 NearLabel loop, done; | |
| 4800 __ bind(&loop); | |
| 4801 // Load the type of the current stack handler. | |
| 4802 const int kStateOffset = StackHandlerConstants::kStateOffset; | |
| 4803 __ cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY)); | |
| 4804 __ j(equal, &done); | |
| 4805 // Fetch the next handler in the list. | |
| 4806 const int kNextOffset = StackHandlerConstants::kNextOffset; | |
| 4807 __ mov(esp, Operand(esp, kNextOffset)); | |
| 4808 __ jmp(&loop); | |
| 4809 __ bind(&done); | |
| 4810 | |
| 4811 // Set the top handler address to next handler past the current ENTRY handler. | |
| 4812 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 4813 __ pop(Operand::StaticVariable(handler_address)); | |
| 4814 | |
| 4815 if (type == OUT_OF_MEMORY) { | |
| 4816 // Set external caught exception to false. | |
| 4817 ExternalReference external_caught( | |
| 4818 Isolate::k_external_caught_exception_address); | |
| 4819 __ mov(eax, false); | |
| 4820 __ mov(Operand::StaticVariable(external_caught), eax); | |
| 4821 | |
| 4822 // Set pending exception and eax to out of memory exception. | |
| 4823 ExternalReference pending_exception(Isolate::k_pending_exception_address); | |
| 4824 __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); | |
| 4825 __ mov(Operand::StaticVariable(pending_exception), eax); | |
| 4826 } | |
| 4827 | |
| 4828 // Clear the context pointer. | |
| 4829 __ Set(esi, Immediate(0)); | |
| 4830 | |
| 4831 // Restore fp from handler and discard handler state. | |
| 4832 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); | |
| 4833 __ pop(ebp); | |
| 4834 __ pop(edx); // State. | |
| 4835 | |
| 4836 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 4837 __ ret(0); | |
| 4838 } | 4790 } |
| 4839 | 4791 |
| 4840 | 4792 |
| 4841 void CEntryStub::Generate(MacroAssembler* masm) { | 4793 void CEntryStub::Generate(MacroAssembler* masm) { |
| 4842 // eax: number of arguments including receiver | 4794 // eax: number of arguments including receiver |
| 4843 // ebx: pointer to C function (C callee-saved) | 4795 // ebx: pointer to C function (C callee-saved) |
| 4844 // ebp: frame pointer (restored after C call) | 4796 // ebp: frame pointer (restored after C call) |
| 4845 // esp: stack pointer (restored after C call) | 4797 // esp: stack pointer (restored after C call) |
| 4846 // esi: current context (C callee-saved) | 4798 // esi: current context (C callee-saved) |
| 4847 // edi: JS function of the caller (C callee-saved) | 4799 // edi: JS function of the caller (C callee-saved) |
| (...skipping 1719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6567 if (key_not_smi != NULL) { | 6519 if (key_not_smi != NULL) { |
| 6568 __ JumpIfNotSmi(key, key_not_smi); | 6520 __ JumpIfNotSmi(key, key_not_smi); |
| 6569 } else { | 6521 } else { |
| 6570 if (FLAG_debug_code) { | 6522 if (FLAG_debug_code) { |
| 6571 __ AbortIfNotSmi(key); | 6523 __ AbortIfNotSmi(key); |
| 6572 } | 6524 } |
| 6573 } | 6525 } |
| 6574 __ mov(untagged_key, key); | 6526 __ mov(untagged_key, key); |
| 6575 __ SmiUntag(untagged_key); | 6527 __ SmiUntag(untagged_key); |
| 6576 | 6528 |
| 6577 // Verify that the receiver has pixel array elements. | |
| 6578 __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset)); | 6529 __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 6579 __ CheckMap(elements, FACTORY->pixel_array_map(), not_pixel_array, true); | 6530 // By passing NULL as not_pixel_array, callers signal that they have already |
| 6531 // verified that the receiver has pixel array elements. |
| 6532 if (not_pixel_array != NULL) { |
| 6533 __ CheckMap(elements, FACTORY->pixel_array_map(), not_pixel_array, true); |
| 6534 } else { |
| 6535 if (FLAG_debug_code) { |
| 6536 // Map check should have already made sure that elements is a pixel array. |
| 6537 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 6538 Immediate(FACTORY->pixel_array_map())); |
| 6539 __ Assert(equal, "Elements isn't a pixel array"); |
| 6540 } |
| 6541 } |
| 6580 | 6542 |
| 6581 // Key must be in range. | 6543 // Key must be in range. |
| 6582 __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset)); | 6544 __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset)); |
| 6583 __ j(above_equal, out_of_range); // unsigned check handles negative keys. | 6545 __ j(above_equal, out_of_range); // unsigned check handles negative keys. |
| 6584 | 6546 |
| 6585 // Perform the indexed load and tag the result as a smi. | 6547 // Perform the indexed load and tag the result as a smi. |
| 6586 __ mov(elements, FieldOperand(elements, PixelArray::kExternalPointerOffset)); | 6548 __ mov(elements, FieldOperand(elements, PixelArray::kExternalPointerOffset)); |
| 6587 __ movzx_b(result, Operand(elements, untagged_key, times_1, 0)); | 6549 __ movzx_b(result, Operand(elements, untagged_key, times_1, 0)); |
| 6588 __ SmiTag(result); | 6550 __ SmiTag(result); |
| 6589 __ ret(0); | 6551 __ ret(0); |
| 6590 } | 6552 } |
| 6591 | 6553 |
| 6592 | 6554 |
| 6555 // Stores an indexed element into a pixel array, clamping the stored value. |
| 6556 void GenerateFastPixelArrayStore(MacroAssembler* masm, |
| 6557 Register receiver, |
| 6558 Register key, |
| 6559 Register value, |
| 6560 Register elements, |
| 6561 Register scratch1, |
| 6562 bool load_elements_from_receiver, |
| 6563 Label* key_not_smi, |
| 6564 Label* value_not_smi, |
| 6565 Label* not_pixel_array, |
| 6566 Label* out_of_range) { |
| 6567 // Register use: |
| 6568 // receiver - holds the receiver and is unchanged unless the |
| 6569 // store succeeds. |
| 6570 // key - holds the key (must be a smi) and is unchanged. |
| 6571 // value - holds the value (must be a smi) and is unchanged. |
| 6572 // elements - holds the element object of the receiver on entry if |
| 6573 // load_elements_from_receiver is false, otherwise used |
| 6574 // internally to store the pixel arrays elements and |
| 6575 // external array pointer. |
| 6576 // |
| 6577 // receiver, key and value remain unmodified until it's guaranteed that the |
| 6578 // store will succeed. |
| 6579 Register external_pointer = elements; |
| 6580 Register untagged_key = scratch1; |
| 6581 Register untagged_value = receiver; // Only set once success guaranteed. |
| 6582 |
| 6583 // Fetch the receiver's elements if the caller hasn't already done so. |
| 6584 if (load_elements_from_receiver) { |
| 6585 __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 6586 } |
| 6587 |
| 6588 // By passing NULL as not_pixel_array, callers signal that they have already |
| 6589 // verified that the receiver has pixel array elements. |
| 6590 if (not_pixel_array != NULL) { |
| 6591 __ CheckMap(elements, FACTORY->pixel_array_map(), not_pixel_array, true); |
| 6592 } else { |
| 6593 if (FLAG_debug_code) { |
| 6594 // Map check should have already made sure that elements is a pixel array. |
| 6595 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 6596 Immediate(FACTORY->pixel_array_map())); |
| 6597 __ Assert(equal, "Elements isn't a pixel array"); |
| 6598 } |
| 6599 } |
| 6600 |
| 6601 // Some callers already have verified that the key is a smi. key_not_smi is |
| 6602 // set to NULL as a sentinel for that case. Otherwise, add an explicit check |
| 6603 // to ensure the key is a smi must be added. |
| 6604 if (key_not_smi != NULL) { |
| 6605 __ JumpIfNotSmi(key, key_not_smi); |
| 6606 } else { |
| 6607 if (FLAG_debug_code) { |
| 6608 __ AbortIfNotSmi(key); |
| 6609 } |
| 6610 } |
| 6611 |
| 6612 // Key must be a smi and it must be in range. |
| 6613 __ mov(untagged_key, key); |
| 6614 __ SmiUntag(untagged_key); |
| 6615 __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset)); |
| 6616 __ j(above_equal, out_of_range); // unsigned check handles negative keys. |
| 6617 |
| 6618 // Value must be a smi. |
| 6619 __ JumpIfNotSmi(value, value_not_smi); |
| 6620 __ mov(untagged_value, value); |
| 6621 __ SmiUntag(untagged_value); |
| 6622 |
| 6623 { // Clamp the value to [0..255]. |
| 6624 NearLabel done; |
| 6625 __ test(untagged_value, Immediate(0xFFFFFF00)); |
| 6626 __ j(zero, &done); |
| 6627 __ setcc(negative, untagged_value); // 1 if negative, 0 if positive. |
| 6628 __ dec_b(untagged_value); // 0 if negative, 255 if positive. |
| 6629 __ bind(&done); |
| 6630 } |
| 6631 |
| 6632 __ mov(external_pointer, |
| 6633 FieldOperand(elements, PixelArray::kExternalPointerOffset)); |
| 6634 __ mov_b(Operand(external_pointer, untagged_key, times_1, 0), untagged_value); |
| 6635 __ ret(0); // Return value in eax. |
| 6636 } |
| 6637 |
| 6638 |
| 6593 #undef __ | 6639 #undef __ |
| 6594 | 6640 |
| 6595 } } // namespace v8::internal | 6641 } } // namespace v8::internal |
| 6596 | 6642 |
| 6597 #endif // V8_TARGET_ARCH_IA32 | 6643 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |