| 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 2398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2409 case Token::SHR: | 2409 case Token::SHR: |
| 2410 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); | 2410 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
| 2411 break; | 2411 break; |
| 2412 default: | 2412 default: |
| 2413 UNREACHABLE(); | 2413 UNREACHABLE(); |
| 2414 } | 2414 } |
| 2415 } | 2415 } |
| 2416 | 2416 |
| 2417 | 2417 |
| 2418 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { | 2418 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
| 2419 NearLabel call_runtime; | 2419 ASSERT(op_ == Token::ADD); |
| 2420 NearLabel left_not_string, call_runtime; |
| 2420 | 2421 |
| 2421 // Registers containing left and right operands respectively. | 2422 // Registers containing left and right operands respectively. |
| 2422 Register left = edx; | 2423 Register left = edx; |
| 2423 Register right = eax; | 2424 Register right = eax; |
| 2424 | 2425 |
| 2425 // Test if left operand is a string. | 2426 // Test if left operand is a string. |
| 2426 NearLabel left_not_string; | |
| 2427 __ test(left, Immediate(kSmiTagMask)); | 2427 __ test(left, Immediate(kSmiTagMask)); |
| 2428 __ j(zero, &left_not_string); | 2428 __ j(zero, &left_not_string); |
| 2429 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 2429 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
| 2430 __ j(above_equal, &left_not_string); | 2430 __ j(above_equal, &left_not_string); |
| 2431 | 2431 |
| 2432 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); | 2432 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
| 2433 GenerateRegisterArgsPush(masm); | 2433 GenerateRegisterArgsPush(masm); |
| 2434 __ TailCallStub(&string_add_left_stub); | 2434 __ TailCallStub(&string_add_left_stub); |
| 2435 | 2435 |
| 2436 // Left operand is not a string, test right. | 2436 // Left operand is not a string, test right. |
| (...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3423 __ cvtsi2sd(xmm3, Operand(ecx)); | 3423 __ cvtsi2sd(xmm3, Operand(ecx)); |
| 3424 | 3424 |
| 3425 Label exponent_nonsmi; | 3425 Label exponent_nonsmi; |
| 3426 Label base_nonsmi; | 3426 Label base_nonsmi; |
| 3427 // If the exponent is a heap number go to that specific case. | 3427 // If the exponent is a heap number go to that specific case. |
| 3428 __ test(eax, Immediate(kSmiTagMask)); | 3428 __ test(eax, Immediate(kSmiTagMask)); |
| 3429 __ j(not_zero, &exponent_nonsmi); | 3429 __ j(not_zero, &exponent_nonsmi); |
| 3430 __ test(edx, Immediate(kSmiTagMask)); | 3430 __ test(edx, Immediate(kSmiTagMask)); |
| 3431 __ j(not_zero, &base_nonsmi); | 3431 __ j(not_zero, &base_nonsmi); |
| 3432 | 3432 |
| 3433 // Optimized version when both exponent and base is a smi. | 3433 // Optimized version when both exponent and base are smis. |
| 3434 Label powi; | 3434 Label powi; |
| 3435 __ SmiUntag(edx); | 3435 __ SmiUntag(edx); |
| 3436 __ cvtsi2sd(xmm0, Operand(edx)); | 3436 __ cvtsi2sd(xmm0, Operand(edx)); |
| 3437 __ jmp(&powi); | 3437 __ jmp(&powi); |
| 3438 // exponent is smi and base is a heapnumber. | 3438 // exponent is smi and base is a heapnumber. |
| 3439 __ bind(&base_nonsmi); | 3439 __ bind(&base_nonsmi); |
| 3440 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3440 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3441 Factory::heap_number_map()); | 3441 Factory::heap_number_map()); |
| 3442 __ j(not_equal, &call_runtime); | 3442 __ j(not_equal, &call_runtime); |
| 3443 | 3443 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3462 // Load xmm1 with 1. | 3462 // Load xmm1 with 1. |
| 3463 __ movsd(xmm1, xmm3); | 3463 __ movsd(xmm1, xmm3); |
| 3464 NearLabel while_true; | 3464 NearLabel while_true; |
| 3465 NearLabel no_multiply; | 3465 NearLabel no_multiply; |
| 3466 | 3466 |
| 3467 __ bind(&while_true); | 3467 __ bind(&while_true); |
| 3468 __ shr(eax, 1); | 3468 __ shr(eax, 1); |
| 3469 __ j(not_carry, &no_multiply); | 3469 __ j(not_carry, &no_multiply); |
| 3470 __ mulsd(xmm1, xmm0); | 3470 __ mulsd(xmm1, xmm0); |
| 3471 __ bind(&no_multiply); | 3471 __ bind(&no_multiply); |
| 3472 __ test(eax, Operand(eax)); | |
| 3473 __ mulsd(xmm0, xmm0); | 3472 __ mulsd(xmm0, xmm0); |
| 3474 __ j(not_zero, &while_true); | 3473 __ j(not_zero, &while_true); |
| 3475 | 3474 |
| 3476 // base has the original value of the exponent - if the exponent is | 3475 // base has the original value of the exponent - if the exponent is |
| 3477 // negative return 1/result. | 3476 // negative return 1/result. |
| 3478 __ test(edx, Operand(edx)); | 3477 __ test(edx, Operand(edx)); |
| 3479 __ j(positive, &allocate_return); | 3478 __ j(positive, &allocate_return); |
| 3480 // Special case if xmm1 has reached infinity. | 3479 // Special case if xmm1 has reached infinity. |
| 3481 __ mov(ecx, Immediate(0x7FB00000)); | 3480 __ mov(ecx, Immediate(0x7FB00000)); |
| 3482 __ movd(xmm0, Operand(ecx)); | 3481 __ movd(xmm0, Operand(ecx)); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3549 // Calculates square root. | 3548 // Calculates square root. |
| 3550 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | 3549 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
| 3551 __ xorpd(xmm1, xmm1); | 3550 __ xorpd(xmm1, xmm1); |
| 3552 __ addsd(xmm1, xmm0); | 3551 __ addsd(xmm1, xmm0); |
| 3553 __ sqrtsd(xmm1, xmm1); | 3552 __ sqrtsd(xmm1, xmm1); |
| 3554 | 3553 |
| 3555 __ bind(&allocate_return); | 3554 __ bind(&allocate_return); |
| 3556 __ AllocateHeapNumber(ecx, eax, edx, &call_runtime); | 3555 __ AllocateHeapNumber(ecx, eax, edx, &call_runtime); |
| 3557 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm1); | 3556 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm1); |
| 3558 __ mov(eax, ecx); | 3557 __ mov(eax, ecx); |
| 3559 __ ret(2); | 3558 __ ret(2 * kPointerSize); |
| 3560 | 3559 |
| 3561 __ bind(&call_runtime); | 3560 __ bind(&call_runtime); |
| 3562 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | 3561 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
| 3563 } | 3562 } |
| 3564 | 3563 |
| 3565 | 3564 |
| 3566 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 3565 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
| 3567 // The key is in edx and the parameter count is in eax. | 3566 // The key is in edx and the parameter count is in eax. |
| 3568 | 3567 |
| 3569 // The displacement is used for skipping the frame pointer on the | 3568 // The displacement is used for skipping the frame pointer on the |
| (...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4676 // of the original receiver from the call site). | 4675 // of the original receiver from the call site). |
| 4677 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); | 4676 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); |
| 4678 __ Set(eax, Immediate(argc_)); | 4677 __ Set(eax, Immediate(argc_)); |
| 4679 __ Set(ebx, Immediate(0)); | 4678 __ Set(ebx, Immediate(0)); |
| 4680 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 4679 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
| 4681 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 4680 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
| 4682 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 4681 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
| 4683 } | 4682 } |
| 4684 | 4683 |
| 4685 | 4684 |
| 4685 bool CEntryStub::NeedsImmovableCode() { |
| 4686 return false; |
| 4687 } |
| 4688 |
| 4689 |
| 4686 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 4690 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 4687 __ Throw(eax); | 4691 __ Throw(eax); |
| 4688 } | 4692 } |
| 4689 | 4693 |
| 4690 | 4694 |
| 4691 void CEntryStub::GenerateCore(MacroAssembler* masm, | 4695 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| 4692 Label* throw_normal_exception, | 4696 Label* throw_normal_exception, |
| 4693 Label* throw_termination_exception, | 4697 Label* throw_termination_exception, |
| 4694 Label* throw_out_of_memory_exception, | 4698 Label* throw_out_of_memory_exception, |
| 4695 bool do_gc, | 4699 bool do_gc, |
| (...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5533 // ebx: length of first string as a smi | 5537 // ebx: length of first string as a smi |
| 5534 // ecx: length of second string as a smi | 5538 // ecx: length of second string as a smi |
| 5535 // edx: second string | 5539 // edx: second string |
| 5536 // Look at the length of the result of adding the two strings. | 5540 // Look at the length of the result of adding the two strings. |
| 5537 Label string_add_flat_result, longer_than_two; | 5541 Label string_add_flat_result, longer_than_two; |
| 5538 __ bind(&both_not_zero_length); | 5542 __ bind(&both_not_zero_length); |
| 5539 __ add(ebx, Operand(ecx)); | 5543 __ add(ebx, Operand(ecx)); |
| 5540 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength); | 5544 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength); |
| 5541 // Handle exceptionally long strings in the runtime system. | 5545 // Handle exceptionally long strings in the runtime system. |
| 5542 __ j(overflow, &string_add_runtime); | 5546 __ j(overflow, &string_add_runtime); |
| 5543 // Use the runtime system when adding two one character strings, as it | 5547 // Use the symbol table when adding two one character strings, as it |
| 5544 // contains optimizations for this specific case using the symbol table. | 5548 // helps later optimizations to return a symbol here. |
| 5545 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2))); | 5549 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2))); |
| 5546 __ j(not_equal, &longer_than_two); | 5550 __ j(not_equal, &longer_than_two); |
| 5547 | 5551 |
| 5548 // Check that both strings are non-external ascii strings. | 5552 // Check that both strings are non-external ascii strings. |
| 5549 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, | 5553 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, |
| 5550 &string_add_runtime); | 5554 &string_add_runtime); |
| 5551 | 5555 |
| 5552 // Get the two characters forming the new string. | 5556 // Get the two characters forming the new string. |
| 5553 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); | 5557 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); |
| 5554 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); | 5558 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5951 STATIC_ASSERT(SymbolTable::kEntrySize == 1); | 5955 STATIC_ASSERT(SymbolTable::kEntrySize == 1); |
| 5952 __ mov(candidate, | 5956 __ mov(candidate, |
| 5953 FieldOperand(symbol_table, | 5957 FieldOperand(symbol_table, |
| 5954 scratch, | 5958 scratch, |
| 5955 times_pointer_size, | 5959 times_pointer_size, |
| 5956 SymbolTable::kElementsStartOffset)); | 5960 SymbolTable::kElementsStartOffset)); |
| 5957 | 5961 |
| 5958 // If entry is undefined no string with this hash can be found. | 5962 // If entry is undefined no string with this hash can be found. |
| 5959 __ cmp(candidate, Factory::undefined_value()); | 5963 __ cmp(candidate, Factory::undefined_value()); |
| 5960 __ j(equal, not_found); | 5964 __ j(equal, not_found); |
| 5965 __ cmp(candidate, Factory::null_value()); |
| 5966 __ j(equal, &next_probe[i]); |
| 5961 | 5967 |
| 5962 // If length is not 2 the string is not a candidate. | 5968 // If length is not 2 the string is not a candidate. |
| 5963 __ cmp(FieldOperand(candidate, String::kLengthOffset), | 5969 __ cmp(FieldOperand(candidate, String::kLengthOffset), |
| 5964 Immediate(Smi::FromInt(2))); | 5970 Immediate(Smi::FromInt(2))); |
| 5965 __ j(not_equal, &next_probe[i]); | 5971 __ j(not_equal, &next_probe[i]); |
| 5966 | 5972 |
| 5967 // As we are out of registers save the mask on the stack and use that | 5973 // As we are out of registers save the mask on the stack and use that |
| 5968 // register as a temporary. | 5974 // register as a temporary. |
| 5969 __ push(mask); | 5975 __ push(mask); |
| 5970 Register temp = mask; | 5976 Register temp = mask; |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6319 __ push(ecx); | 6325 __ push(ecx); |
| 6320 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); | 6326 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); |
| 6321 | 6327 |
| 6322 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 6328 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 6323 // tagged as a small integer. | 6329 // tagged as a small integer. |
| 6324 __ bind(&runtime); | 6330 __ bind(&runtime); |
| 6325 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 6331 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 6326 } | 6332 } |
| 6327 | 6333 |
| 6328 | 6334 |
| 6329 void StringCharAtStub::Generate(MacroAssembler* masm) { | |
| 6330 // Expects two arguments (object, index) on the stack: | |
| 6331 | |
| 6332 // Stack frame on entry. | |
| 6333 // esp[0]: return address | |
| 6334 // esp[4]: index | |
| 6335 // esp[8]: object | |
| 6336 | |
| 6337 Register object = ebx; | |
| 6338 Register index = eax; | |
| 6339 Register scratch1 = ecx; | |
| 6340 Register scratch2 = edx; | |
| 6341 Register result = eax; | |
| 6342 | |
| 6343 __ pop(scratch1); // Return address. | |
| 6344 __ pop(index); | |
| 6345 __ pop(object); | |
| 6346 __ push(scratch1); | |
| 6347 | |
| 6348 Label need_conversion; | |
| 6349 Label index_out_of_range; | |
| 6350 Label done; | |
| 6351 StringCharAtGenerator generator(object, | |
| 6352 index, | |
| 6353 scratch1, | |
| 6354 scratch2, | |
| 6355 result, | |
| 6356 &need_conversion, | |
| 6357 &need_conversion, | |
| 6358 &index_out_of_range, | |
| 6359 STRING_INDEX_IS_NUMBER); | |
| 6360 generator.GenerateFast(masm); | |
| 6361 __ jmp(&done); | |
| 6362 | |
| 6363 __ bind(&index_out_of_range); | |
| 6364 // When the index is out of range, the spec requires us to return | |
| 6365 // the empty string. | |
| 6366 __ Set(result, Immediate(Factory::empty_string())); | |
| 6367 __ jmp(&done); | |
| 6368 | |
| 6369 __ bind(&need_conversion); | |
| 6370 // Move smi zero into the result register, which will trigger | |
| 6371 // conversion. | |
| 6372 __ Set(result, Immediate(Smi::FromInt(0))); | |
| 6373 __ jmp(&done); | |
| 6374 | |
| 6375 StubRuntimeCallHelper call_helper; | |
| 6376 generator.GenerateSlow(masm, call_helper); | |
| 6377 | |
| 6378 __ bind(&done); | |
| 6379 __ ret(0); | |
| 6380 } | |
| 6381 | |
| 6382 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 6335 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
| 6383 ASSERT(state_ == CompareIC::SMIS); | 6336 ASSERT(state_ == CompareIC::SMIS); |
| 6384 NearLabel miss; | 6337 NearLabel miss; |
| 6385 __ mov(ecx, Operand(edx)); | 6338 __ mov(ecx, Operand(edx)); |
| 6386 __ or_(ecx, Operand(eax)); | 6339 __ or_(ecx, Operand(eax)); |
| 6387 __ test(ecx, Immediate(kSmiTagMask)); | 6340 __ test(ecx, Immediate(kSmiTagMask)); |
| 6388 __ j(not_zero, &miss, not_taken); | 6341 __ j(not_zero, &miss, not_taken); |
| 6389 | 6342 |
| 6390 if (GetCondition() == equal) { | 6343 if (GetCondition() == equal) { |
| 6391 // For equality we do not care about the sign of the result. | 6344 // For equality we do not care about the sign of the result. |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6504 __ pop(ecx); | 6457 __ pop(ecx); |
| 6505 __ pop(eax); | 6458 __ pop(eax); |
| 6506 __ pop(edx); | 6459 __ pop(edx); |
| 6507 __ push(ecx); | 6460 __ push(ecx); |
| 6508 | 6461 |
| 6509 // Do a tail call to the rewritten stub. | 6462 // Do a tail call to the rewritten stub. |
| 6510 __ jmp(Operand(edi)); | 6463 __ jmp(Operand(edi)); |
| 6511 } | 6464 } |
| 6512 | 6465 |
| 6513 | 6466 |
| 6514 // Loads a indexed element from a pixel array. | |
| 6515 void GenerateFastPixelArrayLoad(MacroAssembler* masm, | |
| 6516 Register receiver, | |
| 6517 Register key, | |
| 6518 Register elements, | |
| 6519 Register untagged_key, | |
| 6520 Register result, | |
| 6521 Label* not_pixel_array, | |
| 6522 Label* key_not_smi, | |
| 6523 Label* out_of_range) { | |
| 6524 // Register use: | |
| 6525 // receiver - holds the receiver and is unchanged. | |
| 6526 // key - holds the key and is unchanged (must be a smi). | |
| 6527 // elements - is set to the the receiver's element if | |
| 6528 // the receiver doesn't have a pixel array or the | |
| 6529 // key is not a smi, otherwise it's the elements' | |
| 6530 // external pointer. | |
| 6531 // untagged_key - is set to the untagged key | |
| 6532 | |
| 6533 // Some callers already have verified that the key is a smi. key_not_smi is | |
| 6534 // set to NULL as a sentinel for that case. Otherwise, add an explicit check | |
| 6535 // to ensure the key is a smi must be added. | |
| 6536 if (key_not_smi != NULL) { | |
| 6537 __ JumpIfNotSmi(key, key_not_smi); | |
| 6538 } else { | |
| 6539 if (FLAG_debug_code) { | |
| 6540 __ AbortIfNotSmi(key); | |
| 6541 } | |
| 6542 } | |
| 6543 __ mov(untagged_key, key); | |
| 6544 __ SmiUntag(untagged_key); | |
| 6545 | |
| 6546 __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset)); | |
| 6547 // By passing NULL as not_pixel_array, callers signal that they have already | |
| 6548 // verified that the receiver has pixel array elements. | |
| 6549 if (not_pixel_array != NULL) { | |
| 6550 __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true); | |
| 6551 } else { | |
| 6552 if (FLAG_debug_code) { | |
| 6553 // Map check should have already made sure that elements is a pixel array. | |
| 6554 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
| 6555 Immediate(Factory::pixel_array_map())); | |
| 6556 __ Assert(equal, "Elements isn't a pixel array"); | |
| 6557 } | |
| 6558 } | |
| 6559 | |
| 6560 // Key must be in range. | |
| 6561 __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset)); | |
| 6562 __ j(above_equal, out_of_range); // unsigned check handles negative keys. | |
| 6563 | |
| 6564 // Perform the indexed load and tag the result as a smi. | |
| 6565 __ mov(elements, FieldOperand(elements, PixelArray::kExternalPointerOffset)); | |
| 6566 __ movzx_b(result, Operand(elements, untagged_key, times_1, 0)); | |
| 6567 __ SmiTag(result); | |
| 6568 __ ret(0); | |
| 6569 } | |
| 6570 | |
| 6571 | |
| 6572 // Stores an indexed element into a pixel array, clamping the stored value. | |
| 6573 void GenerateFastPixelArrayStore(MacroAssembler* masm, | |
| 6574 Register receiver, | |
| 6575 Register key, | |
| 6576 Register value, | |
| 6577 Register elements, | |
| 6578 Register scratch1, | |
| 6579 bool load_elements_from_receiver, | |
| 6580 Label* key_not_smi, | |
| 6581 Label* value_not_smi, | |
| 6582 Label* not_pixel_array, | |
| 6583 Label* out_of_range) { | |
| 6584 // Register use: | |
| 6585 // receiver - holds the receiver and is unchanged unless the | |
| 6586 // store succeeds. | |
| 6587 // key - holds the key (must be a smi) and is unchanged. | |
| 6588 // value - holds the value (must be a smi) and is unchanged. | |
| 6589 // elements - holds the element object of the receiver on entry if | |
| 6590 // load_elements_from_receiver is false, otherwise used | |
| 6591 // internally to store the pixel arrays elements and | |
| 6592 // external array pointer. | |
| 6593 // | |
| 6594 // receiver, key and value remain unmodified until it's guaranteed that the | |
| 6595 // store will succeed. | |
| 6596 Register external_pointer = elements; | |
| 6597 Register untagged_key = scratch1; | |
| 6598 Register untagged_value = receiver; // Only set once success guaranteed. | |
| 6599 | |
| 6600 // Fetch the receiver's elements if the caller hasn't already done so. | |
| 6601 if (load_elements_from_receiver) { | |
| 6602 __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset)); | |
| 6603 } | |
| 6604 | |
| 6605 // By passing NULL as not_pixel_array, callers signal that they have already | |
| 6606 // verified that the receiver has pixel array elements. | |
| 6607 if (not_pixel_array != NULL) { | |
| 6608 __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true); | |
| 6609 } else { | |
| 6610 if (FLAG_debug_code) { | |
| 6611 // Map check should have already made sure that elements is a pixel array. | |
| 6612 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
| 6613 Immediate(Factory::pixel_array_map())); | |
| 6614 __ Assert(equal, "Elements isn't a pixel array"); | |
| 6615 } | |
| 6616 } | |
| 6617 | |
| 6618 // Some callers already have verified that the key is a smi. key_not_smi is | |
| 6619 // set to NULL as a sentinel for that case. Otherwise, add an explicit check | |
| 6620 // to ensure the key is a smi must be added. | |
| 6621 if (key_not_smi != NULL) { | |
| 6622 __ JumpIfNotSmi(key, key_not_smi); | |
| 6623 } else { | |
| 6624 if (FLAG_debug_code) { | |
| 6625 __ AbortIfNotSmi(key); | |
| 6626 } | |
| 6627 } | |
| 6628 | |
| 6629 // Key must be a smi and it must be in range. | |
| 6630 __ mov(untagged_key, key); | |
| 6631 __ SmiUntag(untagged_key); | |
| 6632 __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset)); | |
| 6633 __ j(above_equal, out_of_range); // unsigned check handles negative keys. | |
| 6634 | |
| 6635 // Value must be a smi. | |
| 6636 __ JumpIfNotSmi(value, value_not_smi); | |
| 6637 __ mov(untagged_value, value); | |
| 6638 __ SmiUntag(untagged_value); | |
| 6639 | |
| 6640 { // Clamp the value to [0..255]. | |
| 6641 NearLabel done; | |
| 6642 __ test(untagged_value, Immediate(0xFFFFFF00)); | |
| 6643 __ j(zero, &done); | |
| 6644 __ setcc(negative, untagged_value); // 1 if negative, 0 if positive. | |
| 6645 __ dec_b(untagged_value); // 0 if negative, 255 if positive. | |
| 6646 __ bind(&done); | |
| 6647 } | |
| 6648 | |
| 6649 __ mov(external_pointer, | |
| 6650 FieldOperand(elements, PixelArray::kExternalPointerOffset)); | |
| 6651 __ mov_b(Operand(external_pointer, untagged_key, times_1, 0), untagged_value); | |
| 6652 __ ret(0); // Return value in eax. | |
| 6653 } | |
| 6654 | |
| 6655 | |
| 6656 void IncrementalMarkingRecordWriteStub::Generate(MacroAssembler* masm) { | 6467 void IncrementalMarkingRecordWriteStub::Generate(MacroAssembler* masm) { |
| 6657 if (IncrementalMarking::IsStopped()) { | 6468 if (IncrementalMarking::IsStopped()) { |
| 6658 __ ret(0); | 6469 __ ret(0); |
| 6659 } else { | 6470 } else { |
| 6660 __ nop(); | 6471 __ nop(); |
| 6661 } | 6472 } |
| 6662 | 6473 |
| 6663 __ IncrementalMarkingRecordWriteHelper(object_, | 6474 __ IncrementalMarkingRecordWriteHelper(object_, |
| 6664 value_, | 6475 value_, |
| 6665 scratch_, | 6476 scratch_, |
| 6666 object_mode_, | 6477 object_mode_, |
| 6667 value_mode_, | 6478 value_mode_, |
| 6668 scratch_mode_); | 6479 scratch_mode_); |
| 6669 __ ret(0); | 6480 __ ret(0); |
| 6670 } | 6481 } |
| 6671 | 6482 |
| 6672 | 6483 |
| 6673 #undef __ | 6484 #undef __ |
| 6674 | 6485 |
| 6675 } } // namespace v8::internal | 6486 } } // namespace v8::internal |
| 6676 | 6487 |
| 6677 #endif // V8_TARGET_ARCH_IA32 | 6488 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |