Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 6614010: [Isolates] Merge 6700:7030 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698