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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 3017018: Change asserts to STATIC_ASSERT if they can be checked at compilation time. ... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 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/arm/codegen-arm.cc ('k') | src/x64/codegen-x64.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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 887 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 dest->false_target()->Branch(zero); 898 dest->false_target()->Branch(zero);
899 value.Unuse(); 899 value.Unuse();
900 dest->Split(not_zero); 900 dest->Split(not_zero);
901 } else if (value.is_number()) { 901 } else if (value.is_number()) {
902 Comment cmnt(masm_, "ONLY_NUMBER"); 902 Comment cmnt(masm_, "ONLY_NUMBER");
903 // Fast case if TypeInfo indicates only numbers. 903 // Fast case if TypeInfo indicates only numbers.
904 if (FLAG_debug_code) { 904 if (FLAG_debug_code) {
905 __ AbortIfNotNumber(value.reg()); 905 __ AbortIfNotNumber(value.reg());
906 } 906 }
907 // Smi => false iff zero. 907 // Smi => false iff zero.
908 ASSERT(kSmiTag == 0); 908 STATIC_ASSERT(kSmiTag == 0);
909 __ test(value.reg(), Operand(value.reg())); 909 __ test(value.reg(), Operand(value.reg()));
910 dest->false_target()->Branch(zero); 910 dest->false_target()->Branch(zero);
911 __ test(value.reg(), Immediate(kSmiTagMask)); 911 __ test(value.reg(), Immediate(kSmiTagMask));
912 dest->true_target()->Branch(zero); 912 dest->true_target()->Branch(zero);
913 __ fldz(); 913 __ fldz();
914 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset)); 914 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
915 __ FCmp(); 915 __ FCmp();
916 value.Unuse(); 916 value.Unuse();
917 dest->Split(not_zero); 917 dest->Split(not_zero);
918 } else { 918 } else {
919 // Fast case checks. 919 // Fast case checks.
920 // 'false' => false. 920 // 'false' => false.
921 __ cmp(value.reg(), Factory::false_value()); 921 __ cmp(value.reg(), Factory::false_value());
922 dest->false_target()->Branch(equal); 922 dest->false_target()->Branch(equal);
923 923
924 // 'true' => true. 924 // 'true' => true.
925 __ cmp(value.reg(), Factory::true_value()); 925 __ cmp(value.reg(), Factory::true_value());
926 dest->true_target()->Branch(equal); 926 dest->true_target()->Branch(equal);
927 927
928 // 'undefined' => false. 928 // 'undefined' => false.
929 __ cmp(value.reg(), Factory::undefined_value()); 929 __ cmp(value.reg(), Factory::undefined_value());
930 dest->false_target()->Branch(equal); 930 dest->false_target()->Branch(equal);
931 931
932 // Smi => false iff zero. 932 // Smi => false iff zero.
933 ASSERT(kSmiTag == 0); 933 STATIC_ASSERT(kSmiTag == 0);
934 __ test(value.reg(), Operand(value.reg())); 934 __ test(value.reg(), Operand(value.reg()));
935 dest->false_target()->Branch(zero); 935 dest->false_target()->Branch(zero);
936 __ test(value.reg(), Immediate(kSmiTagMask)); 936 __ test(value.reg(), Immediate(kSmiTagMask));
937 dest->true_target()->Branch(zero); 937 dest->true_target()->Branch(zero);
938 938
939 // Call the stub for all other cases. 939 // Call the stub for all other cases.
940 frame_->Push(&value); // Undo the Pop() from above. 940 frame_->Push(&value); // Undo the Pop() from above.
941 ToBooleanStub stub; 941 ToBooleanStub stub;
942 Result temp = frame_->CallStub(&stub, 1); 942 Result temp = frame_->CallStub(&stub, 1);
943 // Convert the result to a condition code. 943 // Convert the result to a condition code.
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 __ bind(&done); 1162 __ bind(&done);
1163 } 1163 }
1164 1164
1165 1165
1166 static TypeInfo CalculateTypeInfo(TypeInfo operands_type, 1166 static TypeInfo CalculateTypeInfo(TypeInfo operands_type,
1167 Token::Value op, 1167 Token::Value op,
1168 const Result& right, 1168 const Result& right,
1169 const Result& left) { 1169 const Result& left) {
1170 // Set TypeInfo of result according to the operation performed. 1170 // Set TypeInfo of result according to the operation performed.
1171 // Rely on the fact that smis have a 31 bit payload on ia32. 1171 // Rely on the fact that smis have a 31 bit payload on ia32.
1172 ASSERT(kSmiValueSize == 31); 1172 STATIC_ASSERT(kSmiValueSize == 31);
1173 switch (op) { 1173 switch (op) {
1174 case Token::COMMA: 1174 case Token::COMMA:
1175 return right.type_info(); 1175 return right.type_info();
1176 case Token::OR: 1176 case Token::OR:
1177 case Token::AND: 1177 case Token::AND:
1178 // Result type can be either of the two input types. 1178 // Result type can be either of the two input types.
1179 return operands_type; 1179 return operands_type;
1180 case Token::BIT_AND: { 1180 case Token::BIT_AND: {
1181 // Anding with positive Smis will give you a Smi. 1181 // Anding with positive Smis will give you a Smi.
1182 if (right.is_constant() && right.handle()->IsSmi() && 1182 if (right.is_constant() && right.handle()->IsSmi() &&
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1592 Label non_zero_result; 1592 Label non_zero_result;
1593 __ test(left->reg(), Operand(left->reg())); 1593 __ test(left->reg(), Operand(left->reg()));
1594 __ j(not_zero, &non_zero_result); 1594 __ j(not_zero, &non_zero_result);
1595 __ test(right->reg(), Operand(right->reg())); 1595 __ test(right->reg(), Operand(right->reg()));
1596 deferred->Branch(negative); 1596 deferred->Branch(negative);
1597 __ bind(&non_zero_result); 1597 __ bind(&non_zero_result);
1598 } 1598 }
1599 // Check for the corner case of dividing the most negative smi by 1599 // Check for the corner case of dividing the most negative smi by
1600 // -1. We cannot use the overflow flag, since it is not set by 1600 // -1. We cannot use the overflow flag, since it is not set by
1601 // idiv instruction. 1601 // idiv instruction.
1602 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 1602 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
1603 __ cmp(eax, 0x40000000); 1603 __ cmp(eax, 0x40000000);
1604 deferred->Branch(equal); 1604 deferred->Branch(equal);
1605 // Check that the remainder is zero. 1605 // Check that the remainder is zero.
1606 __ test(edx, Operand(edx)); 1606 __ test(edx, Operand(edx));
1607 deferred->Branch(not_zero); 1607 deferred->Branch(not_zero);
1608 // Tag the result and store it in the quotient register. 1608 // Tag the result and store it in the quotient register.
1609 __ SmiTag(eax); 1609 __ SmiTag(eax);
1610 deferred->BindExit(); 1610 deferred->BindExit();
1611 left->Unuse(); 1611 left->Unuse();
1612 right->Unuse(); 1612 right->Unuse();
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1782 deferred->Branch(overflow); 1782 deferred->Branch(overflow);
1783 break; 1783 break;
1784 1784
1785 case Token::SUB: 1785 case Token::SUB:
1786 __ sub(answer.reg(), Operand(right->reg())); 1786 __ sub(answer.reg(), Operand(right->reg()));
1787 deferred->Branch(overflow); 1787 deferred->Branch(overflow);
1788 break; 1788 break;
1789 1789
1790 case Token::MUL: { 1790 case Token::MUL: {
1791 // If the smi tag is 0 we can just leave the tag on one operand. 1791 // If the smi tag is 0 we can just leave the tag on one operand.
1792 ASSERT(kSmiTag == 0); // Adjust code below if not the case. 1792 STATIC_ASSERT(kSmiTag == 0); // Adjust code below if not the case.
1793 // Remove smi tag from the left operand (but keep sign). 1793 // Remove smi tag from the left operand (but keep sign).
1794 // Left-hand operand has been copied into answer. 1794 // Left-hand operand has been copied into answer.
1795 __ SmiUntag(answer.reg()); 1795 __ SmiUntag(answer.reg());
1796 // Do multiplication of smis, leaving result in answer. 1796 // Do multiplication of smis, leaving result in answer.
1797 __ imul(answer.reg(), Operand(right->reg())); 1797 __ imul(answer.reg(), Operand(right->reg()));
1798 // Go slow on overflows. 1798 // Go slow on overflows.
1799 deferred->Branch(overflow); 1799 deferred->Branch(overflow);
1800 // Check for negative zero result. If product is zero, and one 1800 // Check for negative zero result. If product is zero, and one
1801 // argument is negative, go to slow case. The frame is unchanged 1801 // argument is negative, go to slow case. The frame is unchanged
1802 // in this block, so local control flow can use a Label rather 1802 // in this block, so local control flow can use a Label rather
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
2289 operand->type_info(), 2289 operand->type_info(),
2290 smi_value, 2290 smi_value,
2291 overwrite_mode); 2291 overwrite_mode);
2292 if (!operand->type_info().IsSmi()) { 2292 if (!operand->type_info().IsSmi()) {
2293 __ test(operand->reg(), Immediate(kSmiTagMask)); 2293 __ test(operand->reg(), Immediate(kSmiTagMask));
2294 deferred->Branch(not_zero); 2294 deferred->Branch(not_zero);
2295 } else if (FLAG_debug_code) { 2295 } else if (FLAG_debug_code) {
2296 __ AbortIfNotSmi(operand->reg()); 2296 __ AbortIfNotSmi(operand->reg());
2297 } 2297 }
2298 __ mov(answer.reg(), operand->reg()); 2298 __ mov(answer.reg(), operand->reg());
2299 ASSERT(kSmiTag == 0); // adjust code if not the case 2299 STATIC_ASSERT(kSmiTag == 0); // adjust code if not the case
2300 // We do no shifts, only the Smi conversion, if shift_value is 1. 2300 // We do no shifts, only the Smi conversion, if shift_value is 1.
2301 if (shift_value > 1) { 2301 if (shift_value > 1) {
2302 __ shl(answer.reg(), shift_value - 1); 2302 __ shl(answer.reg(), shift_value - 1);
2303 } 2303 }
2304 // Convert int result to Smi, checking that it is in int range. 2304 // Convert int result to Smi, checking that it is in int range.
2305 ASSERT(kSmiTagSize == 1); // adjust code if not the case 2305 STATIC_ASSERT(kSmiTagSize == 1); // adjust code if not the case
2306 __ add(answer.reg(), Operand(answer.reg())); 2306 __ add(answer.reg(), Operand(answer.reg()));
2307 deferred->Branch(overflow); 2307 deferred->Branch(overflow);
2308 deferred->BindExit(); 2308 deferred->BindExit();
2309 operand->Unuse(); 2309 operand->Unuse();
2310 } 2310 }
2311 } 2311 }
2312 break; 2312 break;
2313 2313
2314 case Token::BIT_OR: 2314 case Token::BIT_OR:
2315 case Token::BIT_XOR: 2315 case Token::BIT_XOR:
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 2363
2364 DeferredInlineSmiOperation* deferred = 2364 DeferredInlineSmiOperation* deferred =
2365 new DeferredInlineSmiOperation(op, 2365 new DeferredInlineSmiOperation(op,
2366 operand->reg(), 2366 operand->reg(),
2367 operand->reg(), 2367 operand->reg(),
2368 operand->type_info(), 2368 operand->type_info(),
2369 smi_value, 2369 smi_value,
2370 overwrite_mode); 2370 overwrite_mode);
2371 // Check that lowest log2(value) bits of operand are zero, and test 2371 // Check that lowest log2(value) bits of operand are zero, and test
2372 // smi tag at the same time. 2372 // smi tag at the same time.
2373 ASSERT_EQ(0, kSmiTag); 2373 STATIC_ASSERT(kSmiTag == 0);
2374 ASSERT_EQ(1, kSmiTagSize); 2374 STATIC_ASSERT(kSmiTagSize == 1);
2375 __ test(operand->reg(), Immediate(3)); 2375 __ test(operand->reg(), Immediate(3));
2376 deferred->Branch(not_zero); // Branch if non-smi or odd smi. 2376 deferred->Branch(not_zero); // Branch if non-smi or odd smi.
2377 __ sar(operand->reg(), 1); 2377 __ sar(operand->reg(), 1);
2378 deferred->BindExit(); 2378 deferred->BindExit();
2379 answer = *operand; 2379 answer = *operand;
2380 } else { 2380 } else {
2381 // Cannot fall through MOD to default case, so we duplicate the 2381 // Cannot fall through MOD to default case, so we duplicate the
2382 // default case here. 2382 // default case here.
2383 Result constant_operand(value); 2383 Result constant_operand(value);
2384 if (reversed) { 2384 if (reversed) {
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2598 ASSERT(temp.is_valid()); 2598 ASSERT(temp.is_valid());
2599 __ mov(temp.reg(), 2599 __ mov(temp.reg(),
2600 FieldOperand(left_side.reg(), HeapObject::kMapOffset)); 2600 FieldOperand(left_side.reg(), HeapObject::kMapOffset));
2601 __ movzx_b(temp.reg(), 2601 __ movzx_b(temp.reg(),
2602 FieldOperand(temp.reg(), Map::kInstanceTypeOffset)); 2602 FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
2603 // If we are testing for equality then make use of the symbol shortcut. 2603 // If we are testing for equality then make use of the symbol shortcut.
2604 // Check if the right left hand side has the same type as the left hand 2604 // Check if the right left hand side has the same type as the left hand
2605 // side (which is always a symbol). 2605 // side (which is always a symbol).
2606 if (cc == equal) { 2606 if (cc == equal) {
2607 Label not_a_symbol; 2607 Label not_a_symbol;
2608 ASSERT(kSymbolTag != 0); 2608 STATIC_ASSERT(kSymbolTag != 0);
2609 // Ensure that no non-strings have the symbol bit set. 2609 // Ensure that no non-strings have the symbol bit set.
2610 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE); 2610 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask);
2611 __ test(temp.reg(), Immediate(kIsSymbolMask)); // Test the symbol bit. 2611 __ test(temp.reg(), Immediate(kIsSymbolMask)); // Test the symbol bit.
2612 __ j(zero, &not_a_symbol); 2612 __ j(zero, &not_a_symbol);
2613 // They are symbols, so do identity compare. 2613 // They are symbols, so do identity compare.
2614 __ cmp(left_side.reg(), right_side.handle()); 2614 __ cmp(left_side.reg(), right_side.handle());
2615 dest->true_target()->Branch(equal); 2615 dest->true_target()->Branch(equal);
2616 dest->false_target()->Branch(not_equal); 2616 dest->false_target()->Branch(not_equal);
2617 __ bind(&not_a_symbol); 2617 __ bind(&not_a_symbol);
2618 } 2618 }
2619 // Call the compare stub if the left side is not a flat ascii string. 2619 // Call the compare stub if the left side is not a flat ascii string.
2620 __ and_(temp.reg(), 2620 __ and_(temp.reg(),
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
3144 // esp[2]: applicand. 3144 // esp[2]: applicand.
3145 3145
3146 // Check that the receiver really is a JavaScript object. 3146 // Check that the receiver really is a JavaScript object.
3147 __ mov(eax, Operand(esp, 0)); 3147 __ mov(eax, Operand(esp, 0));
3148 __ test(eax, Immediate(kSmiTagMask)); 3148 __ test(eax, Immediate(kSmiTagMask));
3149 __ j(zero, &build_args); 3149 __ j(zero, &build_args);
3150 // We allow all JSObjects including JSFunctions. As long as 3150 // We allow all JSObjects including JSFunctions. As long as
3151 // JS_FUNCTION_TYPE is the last instance type and it is right 3151 // JS_FUNCTION_TYPE is the last instance type and it is right
3152 // after LAST_JS_OBJECT_TYPE, we do not have to check the upper 3152 // after LAST_JS_OBJECT_TYPE, we do not have to check the upper
3153 // bound. 3153 // bound.
3154 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 3154 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
3155 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 3155 STATIC_ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
3156 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 3156 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
3157 __ j(below, &build_args); 3157 __ j(below, &build_args);
3158 3158
3159 // Check that applicand.apply is Function.prototype.apply. 3159 // Check that applicand.apply is Function.prototype.apply.
3160 __ mov(eax, Operand(esp, kPointerSize)); 3160 __ mov(eax, Operand(esp, kPointerSize));
3161 __ test(eax, Immediate(kSmiTagMask)); 3161 __ test(eax, Immediate(kSmiTagMask));
3162 __ j(zero, &build_args); 3162 __ j(zero, &build_args);
3163 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ecx); 3163 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ecx);
3164 __ j(not_equal, &build_args); 3164 __ j(not_equal, &build_args);
3165 __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); 3165 __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
(...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after
4469 __ mov(eax, Operand::StaticVariable(handler_address)); 4469 __ mov(eax, Operand::StaticVariable(handler_address));
4470 __ cmp(esp, Operand(eax)); 4470 __ cmp(esp, Operand(eax));
4471 __ Assert(equal, "stack pointer should point to top handler"); 4471 __ Assert(equal, "stack pointer should point to top handler");
4472 } 4472 }
4473 4473
4474 // If we can fall off the end of the try block, unlink from try chain. 4474 // If we can fall off the end of the try block, unlink from try chain.
4475 if (has_valid_frame()) { 4475 if (has_valid_frame()) {
4476 // The next handler address is on top of the frame. Unlink from 4476 // The next handler address is on top of the frame. Unlink from
4477 // the handler list and drop the rest of this handler from the 4477 // the handler list and drop the rest of this handler from the
4478 // frame. 4478 // frame.
4479 ASSERT(StackHandlerConstants::kNextOffset == 0); 4479 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
4480 frame_->EmitPop(Operand::StaticVariable(handler_address)); 4480 frame_->EmitPop(Operand::StaticVariable(handler_address));
4481 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 4481 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
4482 if (has_unlinks) { 4482 if (has_unlinks) {
4483 exit.Jump(); 4483 exit.Jump();
4484 } 4484 }
4485 } 4485 }
4486 4486
4487 // Generate unlink code for the (formerly) shadowing targets that 4487 // Generate unlink code for the (formerly) shadowing targets that
4488 // have been jumped to. Deallocate each shadow target. 4488 // have been jumped to. Deallocate each shadow target.
4489 Result return_value; 4489 Result return_value;
(...skipping 10 matching lines...) Expand all
4500 // Because we can be jumping here (to spilled code) from 4500 // Because we can be jumping here (to spilled code) from
4501 // unspilled code, we need to reestablish a spilled frame at 4501 // unspilled code, we need to reestablish a spilled frame at
4502 // this block. 4502 // this block.
4503 frame_->SpillAll(); 4503 frame_->SpillAll();
4504 4504
4505 // Reload sp from the top handler, because some statements that we 4505 // Reload sp from the top handler, because some statements that we
4506 // break from (eg, for...in) may have left stuff on the stack. 4506 // break from (eg, for...in) may have left stuff on the stack.
4507 __ mov(esp, Operand::StaticVariable(handler_address)); 4507 __ mov(esp, Operand::StaticVariable(handler_address));
4508 frame_->Forget(frame_->height() - handler_height); 4508 frame_->Forget(frame_->height() - handler_height);
4509 4509
4510 ASSERT(StackHandlerConstants::kNextOffset == 0); 4510 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
4511 frame_->EmitPop(Operand::StaticVariable(handler_address)); 4511 frame_->EmitPop(Operand::StaticVariable(handler_address));
4512 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 4512 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
4513 4513
4514 if (i == kReturnShadowIndex) { 4514 if (i == kReturnShadowIndex) {
4515 if (!function_return_is_shadowed_) frame_->PrepareForReturn(); 4515 if (!function_return_is_shadowed_) frame_->PrepareForReturn();
4516 shadows[i]->other_target()->Jump(&return_value); 4516 shadows[i]->other_target()->Jump(&return_value);
4517 } else { 4517 } else {
4518 shadows[i]->other_target()->Jump(); 4518 shadows[i]->other_target()->Jump();
4519 } 4519 }
4520 } 4520 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
4586 } 4586 }
4587 function_return_is_shadowed_ = function_return_was_shadowed; 4587 function_return_is_shadowed_ = function_return_was_shadowed;
4588 4588
4589 // Get an external reference to the handler address. 4589 // Get an external reference to the handler address.
4590 ExternalReference handler_address(Top::k_handler_address); 4590 ExternalReference handler_address(Top::k_handler_address);
4591 4591
4592 // If we can fall off the end of the try block, unlink from the try 4592 // If we can fall off the end of the try block, unlink from the try
4593 // chain and set the state on the frame to FALLING. 4593 // chain and set the state on the frame to FALLING.
4594 if (has_valid_frame()) { 4594 if (has_valid_frame()) {
4595 // The next handler address is on top of the frame. 4595 // The next handler address is on top of the frame.
4596 ASSERT(StackHandlerConstants::kNextOffset == 0); 4596 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
4597 frame_->EmitPop(Operand::StaticVariable(handler_address)); 4597 frame_->EmitPop(Operand::StaticVariable(handler_address));
4598 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 4598 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
4599 4599
4600 // Fake a top of stack value (unneeded when FALLING) and set the 4600 // Fake a top of stack value (unneeded when FALLING) and set the
4601 // state in ecx, then jump around the unlink blocks if any. 4601 // state in ecx, then jump around the unlink blocks if any.
4602 frame_->EmitPush(Immediate(Factory::undefined_value())); 4602 frame_->EmitPush(Immediate(Factory::undefined_value()));
4603 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); 4603 __ Set(ecx, Immediate(Smi::FromInt(FALLING)));
4604 if (nof_unlinks > 0) { 4604 if (nof_unlinks > 0) {
4605 finally_block.Jump(); 4605 finally_block.Jump();
4606 } 4606 }
(...skipping 18 matching lines...) Expand all
4625 // this block. 4625 // this block.
4626 frame_->SpillAll(); 4626 frame_->SpillAll();
4627 4627
4628 // Reload sp from the top handler, because some statements that 4628 // Reload sp from the top handler, because some statements that
4629 // we break from (eg, for...in) may have left stuff on the 4629 // we break from (eg, for...in) may have left stuff on the
4630 // stack. 4630 // stack.
4631 __ mov(esp, Operand::StaticVariable(handler_address)); 4631 __ mov(esp, Operand::StaticVariable(handler_address));
4632 frame_->Forget(frame_->height() - handler_height); 4632 frame_->Forget(frame_->height() - handler_height);
4633 4633
4634 // Unlink this handler and drop it from the frame. 4634 // Unlink this handler and drop it from the frame.
4635 ASSERT(StackHandlerConstants::kNextOffset == 0); 4635 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
4636 frame_->EmitPop(Operand::StaticVariable(handler_address)); 4636 frame_->EmitPop(Operand::StaticVariable(handler_address));
4637 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 4637 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
4638 4638
4639 if (i == kReturnShadowIndex) { 4639 if (i == kReturnShadowIndex) {
4640 // If this target shadowed the function return, materialize 4640 // If this target shadowed the function return, materialize
4641 // the return value on the stack. 4641 // the return value on the stack.
4642 frame_->EmitPush(eax); 4642 frame_->EmitPush(eax);
4643 } else { 4643 } else {
4644 // Fake TOS for targets that shadowed breaks and continues. 4644 // Fake TOS for targets that shadowed breaks and continues.
4645 frame_->EmitPush(Immediate(Factory::undefined_value())); 4645 frame_->EmitPush(Immediate(Factory::undefined_value()));
(...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after
6566 null.Branch(zero); 6566 null.Branch(zero);
6567 6567
6568 // Check that the object is a JS object but take special care of JS 6568 // Check that the object is a JS object but take special care of JS
6569 // functions to make sure they have 'Function' as their class. 6569 // functions to make sure they have 'Function' as their class.
6570 __ CmpObjectType(obj.reg(), FIRST_JS_OBJECT_TYPE, obj.reg()); 6570 __ CmpObjectType(obj.reg(), FIRST_JS_OBJECT_TYPE, obj.reg());
6571 null.Branch(below); 6571 null.Branch(below);
6572 6572
6573 // As long as JS_FUNCTION_TYPE is the last instance type and it is 6573 // As long as JS_FUNCTION_TYPE is the last instance type and it is
6574 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 6574 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
6575 // LAST_JS_OBJECT_TYPE. 6575 // LAST_JS_OBJECT_TYPE.
6576 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 6576 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
6577 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 6577 STATIC_ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
6578 __ CmpInstanceType(obj.reg(), JS_FUNCTION_TYPE); 6578 __ CmpInstanceType(obj.reg(), JS_FUNCTION_TYPE);
6579 function.Branch(equal); 6579 function.Branch(equal);
6580 6580
6581 // Check if the constructor in the map is a function. 6581 // Check if the constructor in the map is a function.
6582 { Result tmp = allocator()->Allocate(); 6582 { Result tmp = allocator()->Allocate();
6583 __ mov(obj.reg(), FieldOperand(obj.reg(), Map::kConstructorOffset)); 6583 __ mov(obj.reg(), FieldOperand(obj.reg(), Map::kConstructorOffset));
6584 __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, tmp.reg()); 6584 __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, tmp.reg());
6585 non_function_constructor.Branch(not_equal); 6585 non_function_constructor.Branch(not_equal);
6586 } 6586 }
6587 6587
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
6708 left.ToRegister(); 6708 left.ToRegister();
6709 __ cmp(right.reg(), Operand(left.reg())); 6709 __ cmp(right.reg(), Operand(left.reg()));
6710 right.Unuse(); 6710 right.Unuse();
6711 left.Unuse(); 6711 left.Unuse();
6712 destination()->Split(equal); 6712 destination()->Split(equal);
6713 } 6713 }
6714 6714
6715 6715
6716 void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) { 6716 void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) {
6717 ASSERT(args->length() == 0); 6717 ASSERT(args->length() == 0);
6718 ASSERT(kSmiTag == 0); // EBP value is aligned, so it should look like Smi. 6718 STATIC_ASSERT(kSmiTag == 0); // EBP value is aligned, so it looks like a Smi.
6719 Result ebp_as_smi = allocator_->Allocate(); 6719 Result ebp_as_smi = allocator_->Allocate();
6720 ASSERT(ebp_as_smi.is_valid()); 6720 ASSERT(ebp_as_smi.is_valid());
6721 __ mov(ebp_as_smi.reg(), Operand(ebp)); 6721 __ mov(ebp_as_smi.reg(), Operand(ebp));
6722 frame_->Push(&ebp_as_smi); 6722 frame_->Push(&ebp_as_smi);
6723 } 6723 }
6724 6724
6725 6725
6726 void CodeGenerator::GenerateRandomHeapNumber( 6726 void CodeGenerator::GenerateRandomHeapNumber(
6727 ZoneList<Expression*>* args) { 6727 ZoneList<Expression*>* args) {
6728 ASSERT(args->length() == 0); 6728 ASSERT(args->length() == 0);
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
7062 FieldOperand(cache.reg(), FixedArray::OffsetOfElementAt(cache_id))); 7062 FieldOperand(cache.reg(), FixedArray::OffsetOfElementAt(cache_id)));
7063 7063
7064 Result tmp = allocator()->Allocate(); 7064 Result tmp = allocator()->Allocate();
7065 ASSERT(tmp.is_valid()); 7065 ASSERT(tmp.is_valid());
7066 7066
7067 DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(), 7067 DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(),
7068 cache.reg(), 7068 cache.reg(),
7069 key.reg()); 7069 key.reg());
7070 7070
7071 // tmp.reg() now holds finger offset as a smi. 7071 // tmp.reg() now holds finger offset as a smi.
7072 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 7072 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
7073 __ mov(tmp.reg(), FieldOperand(cache.reg(), 7073 __ mov(tmp.reg(), FieldOperand(cache.reg(),
7074 JSFunctionResultCache::kFingerOffset)); 7074 JSFunctionResultCache::kFingerOffset));
7075 __ cmp(key.reg(), FixedArrayElementOperand(cache.reg(), tmp.reg())); 7075 __ cmp(key.reg(), FixedArrayElementOperand(cache.reg(), tmp.reg()));
7076 deferred->Branch(not_equal); 7076 deferred->Branch(not_equal);
7077 7077
7078 __ mov(tmp.reg(), FixedArrayElementOperand(cache.reg(), tmp.reg(), 1)); 7078 __ mov(tmp.reg(), FixedArrayElementOperand(cache.reg(), tmp.reg(), 1));
7079 7079
7080 deferred->BindExit(); 7080 deferred->BindExit();
7081 frame_->Push(&tmp); 7081 frame_->Push(&tmp);
7082 } 7082 }
(...skipping 1941 matching lines...) Expand 10 before | Expand all | Expand 10 after
9024 __ Assert(equal, "JSObject with fast elements map has slow elements"); 9024 __ Assert(equal, "JSObject with fast elements map has slow elements");
9025 } 9025 }
9026 9026
9027 // Check that the key is within bounds. 9027 // Check that the key is within bounds.
9028 __ cmp(key.reg(), 9028 __ cmp(key.reg(),
9029 FieldOperand(elements.reg(), FixedArray::kLengthOffset)); 9029 FieldOperand(elements.reg(), FixedArray::kLengthOffset));
9030 deferred->Branch(above_equal); 9030 deferred->Branch(above_equal);
9031 9031
9032 // Load and check that the result is not the hole. 9032 // Load and check that the result is not the hole.
9033 // Key holds a smi. 9033 // Key holds a smi.
9034 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 9034 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
9035 __ mov(elements.reg(), 9035 __ mov(elements.reg(),
9036 FieldOperand(elements.reg(), 9036 FieldOperand(elements.reg(),
9037 key.reg(), 9037 key.reg(),
9038 times_2, 9038 times_2,
9039 FixedArray::kHeaderSize)); 9039 FixedArray::kHeaderSize));
9040 result = elements; 9040 result = elements;
9041 __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value())); 9041 __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value()));
9042 deferred->Branch(equal); 9042 deferred->Branch(equal);
9043 __ IncrementCounter(&Counters::keyed_load_inline, 1); 9043 __ IncrementCounter(&Counters::keyed_load_inline, 1);
9044 9044
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
9400 9400
9401 // All sizes here are multiples of kPointerSize. 9401 // All sizes here are multiples of kPointerSize.
9402 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0; 9402 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0;
9403 int size = JSArray::kSize + elements_size; 9403 int size = JSArray::kSize + elements_size;
9404 9404
9405 // Load boilerplate object into ecx and check if we need to create a 9405 // Load boilerplate object into ecx and check if we need to create a
9406 // boilerplate. 9406 // boilerplate.
9407 Label slow_case; 9407 Label slow_case;
9408 __ mov(ecx, Operand(esp, 3 * kPointerSize)); 9408 __ mov(ecx, Operand(esp, 3 * kPointerSize));
9409 __ mov(eax, Operand(esp, 2 * kPointerSize)); 9409 __ mov(eax, Operand(esp, 2 * kPointerSize));
9410 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 9410 STATIC_ASSERT(kPointerSize == 4);
9411 STATIC_ASSERT(kSmiTagSize == 1);
9412 STATIC_ASSERT(kSmiTag == 0);
9411 __ mov(ecx, CodeGenerator::FixedArrayElementOperand(ecx, eax)); 9413 __ mov(ecx, CodeGenerator::FixedArrayElementOperand(ecx, eax));
9412 __ cmp(ecx, Factory::undefined_value()); 9414 __ cmp(ecx, Factory::undefined_value());
9413 __ j(equal, &slow_case); 9415 __ j(equal, &slow_case);
9414 9416
9415 // Allocate both the JS array and the elements array in one big 9417 // Allocate both the JS array and the elements array in one big
9416 // allocation. This avoids multiple limit checks. 9418 // allocation. This avoids multiple limit checks.
9417 __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT); 9419 __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT);
9418 9420
9419 // Copy the JS array part. 9421 // Copy the JS array part.
9420 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 9422 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
9464 1 << Map::kIsUndetectable); 9466 1 << Map::kIsUndetectable);
9465 __ j(not_zero, &false_result); 9467 __ j(not_zero, &false_result);
9466 9468
9467 // JavaScript object => true. 9469 // JavaScript object => true.
9468 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE); 9470 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE);
9469 __ j(above_equal, &true_result); 9471 __ j(above_equal, &true_result);
9470 9472
9471 // String value => false iff empty. 9473 // String value => false iff empty.
9472 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE); 9474 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
9473 __ j(above_equal, &not_string); 9475 __ j(above_equal, &not_string);
9474 ASSERT(kSmiTag == 0); 9476 STATIC_ASSERT(kSmiTag == 0);
9475 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0)); 9477 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0));
9476 __ j(zero, &false_result); 9478 __ j(zero, &false_result);
9477 __ jmp(&true_result); 9479 __ jmp(&true_result);
9478 9480
9479 __ bind(&not_string); 9481 __ bind(&not_string);
9480 // HeapNumber => false iff +0, -0, or NaN. 9482 // HeapNumber => false iff +0, -0, or NaN.
9481 __ cmp(edx, Factory::heap_number_map()); 9483 __ cmp(edx, Factory::heap_number_map());
9482 __ j(not_equal, &true_result); 9484 __ j(not_equal, &true_result);
9483 __ fldz(); 9485 __ fldz();
9484 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 9486 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
9714 __ mov(ecx, right); 9716 __ mov(ecx, right);
9715 __ or_(right, Operand(left)); 9717 __ or_(right, Operand(left));
9716 combined = right; 9718 combined = right;
9717 break; 9719 break;
9718 9720
9719 default: 9721 default:
9720 break; 9722 break;
9721 } 9723 }
9722 9724
9723 // 3. Perform the smi check of the operands. 9725 // 3. Perform the smi check of the operands.
9724 ASSERT(kSmiTag == 0); // Adjust zero check if not the case. 9726 STATIC_ASSERT(kSmiTag == 0); // Adjust zero check if not the case.
9725 __ test(combined, Immediate(kSmiTagMask)); 9727 __ test(combined, Immediate(kSmiTagMask));
9726 __ j(not_zero, &not_smis, not_taken); 9728 __ j(not_zero, &not_smis, not_taken);
9727 9729
9728 // 4. Operands are both smis, perform the operation leaving the result in 9730 // 4. Operands are both smis, perform the operation leaving the result in
9729 // eax and check the result if necessary. 9731 // eax and check the result if necessary.
9730 Comment perform_smi(masm, "-- Perform smi operation"); 9732 Comment perform_smi(masm, "-- Perform smi operation");
9731 Label use_fp_on_smis; 9733 Label use_fp_on_smis;
9732 switch (op_) { 9734 switch (op_) {
9733 case Token::BIT_OR: 9735 case Token::BIT_OR:
9734 // Nothing to do. 9736 // Nothing to do.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
9795 break; 9797 break;
9796 9798
9797 case Token::SUB: 9799 case Token::SUB:
9798 __ sub(left, Operand(right)); 9800 __ sub(left, Operand(right));
9799 __ j(overflow, &use_fp_on_smis, not_taken); 9801 __ j(overflow, &use_fp_on_smis, not_taken);
9800 __ mov(eax, left); 9802 __ mov(eax, left);
9801 break; 9803 break;
9802 9804
9803 case Token::MUL: 9805 case Token::MUL:
9804 // If the smi tag is 0 we can just leave the tag on one operand. 9806 // If the smi tag is 0 we can just leave the tag on one operand.
9805 ASSERT(kSmiTag == 0); // Adjust code below if not the case. 9807 STATIC_ASSERT(kSmiTag == 0); // Adjust code below if not the case.
9806 // We can't revert the multiplication if the result is not a smi 9808 // We can't revert the multiplication if the result is not a smi
9807 // so save the right operand. 9809 // so save the right operand.
9808 __ mov(ebx, right); 9810 __ mov(ebx, right);
9809 // Remove tag from one of the operands (but keep sign). 9811 // Remove tag from one of the operands (but keep sign).
9810 __ SmiUntag(right); 9812 __ SmiUntag(right);
9811 // Do multiplication. 9813 // Do multiplication.
9812 __ imul(right, Operand(left)); // Multiplication is commutative. 9814 __ imul(right, Operand(left)); // Multiplication is commutative.
9813 __ j(overflow, &use_fp_on_smis, not_taken); 9815 __ j(overflow, &use_fp_on_smis, not_taken);
9814 // Check for negative zero result. Use combined = left | right. 9816 // Check for negative zero result. Use combined = left | right.
9815 __ NegativeZeroTest(right, combined, &use_fp_on_smis); 9817 __ NegativeZeroTest(right, combined, &use_fp_on_smis);
9816 break; 9818 break;
9817 9819
9818 case Token::DIV: 9820 case Token::DIV:
9819 // We can't revert the division if the result is not a smi so 9821 // We can't revert the division if the result is not a smi so
9820 // save the left operand. 9822 // save the left operand.
9821 __ mov(edi, left); 9823 __ mov(edi, left);
9822 // Check for 0 divisor. 9824 // Check for 0 divisor.
9823 __ test(right, Operand(right)); 9825 __ test(right, Operand(right));
9824 __ j(zero, &use_fp_on_smis, not_taken); 9826 __ j(zero, &use_fp_on_smis, not_taken);
9825 // Sign extend left into edx:eax. 9827 // Sign extend left into edx:eax.
9826 ASSERT(left.is(eax)); 9828 ASSERT(left.is(eax));
9827 __ cdq(); 9829 __ cdq();
9828 // Divide edx:eax by right. 9830 // Divide edx:eax by right.
9829 __ idiv(right); 9831 __ idiv(right);
9830 // Check for the corner case of dividing the most negative smi by 9832 // Check for the corner case of dividing the most negative smi by
9831 // -1. We cannot use the overflow flag, since it is not set by idiv 9833 // -1. We cannot use the overflow flag, since it is not set by idiv
9832 // instruction. 9834 // instruction.
9833 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 9835 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
9834 __ cmp(eax, 0x40000000); 9836 __ cmp(eax, 0x40000000);
9835 __ j(equal, &use_fp_on_smis); 9837 __ j(equal, &use_fp_on_smis);
9836 // Check for negative zero result. Use combined = left | right. 9838 // Check for negative zero result. Use combined = left | right.
9837 __ NegativeZeroTest(eax, combined, &use_fp_on_smis); 9839 __ NegativeZeroTest(eax, combined, &use_fp_on_smis);
9838 // Check that the remainder is zero. 9840 // Check that the remainder is zero.
9839 __ test(edx, Operand(edx)); 9841 __ test(edx, Operand(edx));
9840 __ j(not_zero, &use_fp_on_smis); 9842 __ j(not_zero, &use_fp_on_smis);
9841 // Tag the result and store it in register eax. 9843 // Tag the result and store it in register eax.
9842 __ SmiTag(eax); 9844 __ SmiTag(eax);
9843 break; 9845 break;
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
10396 // Test that eax is a number. 10398 // Test that eax is a number.
10397 Label runtime_call; 10399 Label runtime_call;
10398 Label runtime_call_clear_stack; 10400 Label runtime_call_clear_stack;
10399 Label input_not_smi; 10401 Label input_not_smi;
10400 Label loaded; 10402 Label loaded;
10401 __ mov(eax, Operand(esp, kPointerSize)); 10403 __ mov(eax, Operand(esp, kPointerSize));
10402 __ test(eax, Immediate(kSmiTagMask)); 10404 __ test(eax, Immediate(kSmiTagMask));
10403 __ j(not_zero, &input_not_smi); 10405 __ j(not_zero, &input_not_smi);
10404 // Input is a smi. Untag and load it onto the FPU stack. 10406 // Input is a smi. Untag and load it onto the FPU stack.
10405 // Then load the low and high words of the double into ebx, edx. 10407 // Then load the low and high words of the double into ebx, edx.
10406 ASSERT_EQ(1, kSmiTagSize); 10408 STATIC_ASSERT(kSmiTagSize == 1);
10407 __ sar(eax, 1); 10409 __ sar(eax, 1);
10408 __ sub(Operand(esp), Immediate(2 * kPointerSize)); 10410 __ sub(Operand(esp), Immediate(2 * kPointerSize));
10409 __ mov(Operand(esp, 0), eax); 10411 __ mov(Operand(esp, 0), eax);
10410 __ fild_s(Operand(esp, 0)); 10412 __ fild_s(Operand(esp, 0));
10411 __ fst_d(Operand(esp, 0)); 10413 __ fst_d(Operand(esp, 0));
10412 __ pop(edx); 10414 __ pop(edx);
10413 __ pop(ebx); 10415 __ pop(ebx);
10414 __ jmp(&loaded); 10416 __ jmp(&loaded);
10415 __ bind(&input_not_smi); 10417 __ bind(&input_not_smi);
10416 // Check if input is a HeapNumber. 10418 // Check if input is a HeapNumber.
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after
11115 CpuFeatures::IsSupported(SSE3), 11117 CpuFeatures::IsSupported(SSE3),
11116 &slow); 11118 &slow);
11117 11119
11118 // Do the bitwise operation and check if the result fits in a smi. 11120 // Do the bitwise operation and check if the result fits in a smi.
11119 Label try_float; 11121 Label try_float;
11120 __ not_(ecx); 11122 __ not_(ecx);
11121 __ cmp(ecx, 0xc0000000); 11123 __ cmp(ecx, 0xc0000000);
11122 __ j(sign, &try_float, not_taken); 11124 __ j(sign, &try_float, not_taken);
11123 11125
11124 // Tag the result as a smi and we're done. 11126 // Tag the result as a smi and we're done.
11125 ASSERT(kSmiTagSize == 1); 11127 STATIC_ASSERT(kSmiTagSize == 1);
11126 __ lea(eax, Operand(ecx, times_2, kSmiTag)); 11128 __ lea(eax, Operand(ecx, times_2, kSmiTag));
11127 __ jmp(&done); 11129 __ jmp(&done);
11128 11130
11129 // Try to store the result in a heap number. 11131 // Try to store the result in a heap number.
11130 __ bind(&try_float); 11132 __ bind(&try_float);
11131 if (overwrite_ == UNARY_NO_OVERWRITE) { 11133 if (overwrite_ == UNARY_NO_OVERWRITE) {
11132 // Allocate a fresh heap number, but don't overwrite eax until 11134 // Allocate a fresh heap number, but don't overwrite eax until
11133 // we're sure we can do it without going through the slow case 11135 // we're sure we can do it without going through the slow case
11134 // that needs the value in eax. 11136 // that needs the value in eax.
11135 __ AllocateHeapNumber(ebx, edx, edi, &slow); 11137 __ AllocateHeapNumber(ebx, edx, edi, &slow);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
11191 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 11193 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
11192 __ j(equal, &adaptor); 11194 __ j(equal, &adaptor);
11193 11195
11194 // Check index against formal parameters count limit passed in 11196 // Check index against formal parameters count limit passed in
11195 // through register eax. Use unsigned comparison to get negative 11197 // through register eax. Use unsigned comparison to get negative
11196 // check for free. 11198 // check for free.
11197 __ cmp(edx, Operand(eax)); 11199 __ cmp(edx, Operand(eax));
11198 __ j(above_equal, &slow, not_taken); 11200 __ j(above_equal, &slow, not_taken);
11199 11201
11200 // Read the argument from the stack and return it. 11202 // Read the argument from the stack and return it.
11201 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // shifting code depends on this 11203 STATIC_ASSERT(kSmiTagSize == 1);
11204 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these.
11202 __ lea(ebx, Operand(ebp, eax, times_2, 0)); 11205 __ lea(ebx, Operand(ebp, eax, times_2, 0));
11203 __ neg(edx); 11206 __ neg(edx);
11204 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); 11207 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
11205 __ ret(0); 11208 __ ret(0);
11206 11209
11207 // Arguments adaptor case: Check index against actual arguments 11210 // Arguments adaptor case: Check index against actual arguments
11208 // limit found in the arguments adaptor frame. Use unsigned 11211 // limit found in the arguments adaptor frame. Use unsigned
11209 // comparison to get negative check for free. 11212 // comparison to get negative check for free.
11210 __ bind(&adaptor); 11213 __ bind(&adaptor);
11211 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 11214 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
11212 __ cmp(edx, Operand(ecx)); 11215 __ cmp(edx, Operand(ecx));
11213 __ j(above_equal, &slow, not_taken); 11216 __ j(above_equal, &slow, not_taken);
11214 11217
11215 // Read the argument from the stack and return it. 11218 // Read the argument from the stack and return it.
11216 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // shifting code depends on this 11219 STATIC_ASSERT(kSmiTagSize == 1);
11220 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these.
11217 __ lea(ebx, Operand(ebx, ecx, times_2, 0)); 11221 __ lea(ebx, Operand(ebx, ecx, times_2, 0));
11218 __ neg(edx); 11222 __ neg(edx);
11219 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); 11223 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
11220 __ ret(0); 11224 __ ret(0);
11221 11225
11222 // Slow-case: Handle non-smi or out-of-bounds access to arguments 11226 // Slow-case: Handle non-smi or out-of-bounds access to arguments
11223 // by calling the runtime system. 11227 // by calling the runtime system.
11224 __ bind(&slow); 11228 __ bind(&slow);
11225 __ pop(ebx); // Return address. 11229 __ pop(ebx); // Return address.
11226 __ push(edx); 11230 __ push(edx);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
11277 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset)); 11281 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset));
11278 __ mov(edi, Operand(edi, offset)); 11282 __ mov(edi, Operand(edi, offset));
11279 11283
11280 // Copy the JS object part. 11284 // Copy the JS object part.
11281 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { 11285 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
11282 __ mov(ebx, FieldOperand(edi, i)); 11286 __ mov(ebx, FieldOperand(edi, i));
11283 __ mov(FieldOperand(eax, i), ebx); 11287 __ mov(FieldOperand(eax, i), ebx);
11284 } 11288 }
11285 11289
11286 // Setup the callee in-object property. 11290 // Setup the callee in-object property.
11287 ASSERT(Heap::arguments_callee_index == 0); 11291 STATIC_ASSERT(Heap::arguments_callee_index == 0);
11288 __ mov(ebx, Operand(esp, 3 * kPointerSize)); 11292 __ mov(ebx, Operand(esp, 3 * kPointerSize));
11289 __ mov(FieldOperand(eax, JSObject::kHeaderSize), ebx); 11293 __ mov(FieldOperand(eax, JSObject::kHeaderSize), ebx);
11290 11294
11291 // Get the length (smi tagged) and set that as an in-object property too. 11295 // Get the length (smi tagged) and set that as an in-object property too.
11292 ASSERT(Heap::arguments_length_index == 1); 11296 STATIC_ASSERT(Heap::arguments_length_index == 1);
11293 __ mov(ecx, Operand(esp, 1 * kPointerSize)); 11297 __ mov(ecx, Operand(esp, 1 * kPointerSize));
11294 __ mov(FieldOperand(eax, JSObject::kHeaderSize + kPointerSize), ecx); 11298 __ mov(FieldOperand(eax, JSObject::kHeaderSize + kPointerSize), ecx);
11295 11299
11296 // If there are no actual arguments, we're done. 11300 // If there are no actual arguments, we're done.
11297 Label done; 11301 Label done;
11298 __ test(ecx, Operand(ecx)); 11302 __ test(ecx, Operand(ecx));
11299 __ j(zero, &done); 11303 __ j(zero, &done);
11300 11304
11301 // Get the parameters pointer from the stack. 11305 // Get the parameters pointer from the stack.
11302 __ mov(edx, Operand(esp, 2 * kPointerSize)); 11306 __ mov(edx, Operand(esp, 2 * kPointerSize));
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
11361 ExternalReference address_of_regexp_stack_memory_address = 11365 ExternalReference address_of_regexp_stack_memory_address =
11362 ExternalReference::address_of_regexp_stack_memory_address(); 11366 ExternalReference::address_of_regexp_stack_memory_address();
11363 ExternalReference address_of_regexp_stack_memory_size = 11367 ExternalReference address_of_regexp_stack_memory_size =
11364 ExternalReference::address_of_regexp_stack_memory_size(); 11368 ExternalReference::address_of_regexp_stack_memory_size();
11365 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); 11369 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
11366 __ test(ebx, Operand(ebx)); 11370 __ test(ebx, Operand(ebx));
11367 __ j(zero, &runtime, not_taken); 11371 __ j(zero, &runtime, not_taken);
11368 11372
11369 // Check that the first argument is a JSRegExp object. 11373 // Check that the first argument is a JSRegExp object.
11370 __ mov(eax, Operand(esp, kJSRegExpOffset)); 11374 __ mov(eax, Operand(esp, kJSRegExpOffset));
11371 ASSERT_EQ(0, kSmiTag); 11375 STATIC_ASSERT(kSmiTag == 0);
11372 __ test(eax, Immediate(kSmiTagMask)); 11376 __ test(eax, Immediate(kSmiTagMask));
11373 __ j(zero, &runtime); 11377 __ j(zero, &runtime);
11374 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); 11378 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx);
11375 __ j(not_equal, &runtime); 11379 __ j(not_equal, &runtime);
11376 // Check that the RegExp has been compiled (data contains a fixed array). 11380 // Check that the RegExp has been compiled (data contains a fixed array).
11377 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); 11381 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
11378 if (FLAG_debug_code) { 11382 if (FLAG_debug_code) {
11379 __ test(ecx, Immediate(kSmiTagMask)); 11383 __ test(ecx, Immediate(kSmiTagMask));
11380 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); 11384 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected");
11381 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); 11385 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx);
11382 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); 11386 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
11383 } 11387 }
11384 11388
11385 // ecx: RegExp data (FixedArray) 11389 // ecx: RegExp data (FixedArray)
11386 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 11390 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
11387 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset)); 11391 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset));
11388 __ cmp(Operand(ebx), Immediate(Smi::FromInt(JSRegExp::IRREGEXP))); 11392 __ cmp(Operand(ebx), Immediate(Smi::FromInt(JSRegExp::IRREGEXP)));
11389 __ j(not_equal, &runtime); 11393 __ j(not_equal, &runtime);
11390 11394
11391 // ecx: RegExp data (FixedArray) 11395 // ecx: RegExp data (FixedArray)
11392 // Check that the number of captures fit in the static offsets vector buffer. 11396 // Check that the number of captures fit in the static offsets vector buffer.
11393 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); 11397 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
11394 // Calculate number of capture registers (number_of_captures + 1) * 2. This 11398 // Calculate number of capture registers (number_of_captures + 1) * 2. This
11395 // uses the asumption that smis are 2 * their untagged value. 11399 // uses the asumption that smis are 2 * their untagged value.
11396 ASSERT_EQ(0, kSmiTag); 11400 STATIC_ASSERT(kSmiTag == 0);
11397 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 11401 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
11398 __ add(Operand(edx), Immediate(2)); // edx was a smi. 11402 __ add(Operand(edx), Immediate(2)); // edx was a smi.
11399 // Check that the static offsets vector buffer is large enough. 11403 // Check that the static offsets vector buffer is large enough.
11400 __ cmp(edx, OffsetsVector::kStaticOffsetsVectorSize); 11404 __ cmp(edx, OffsetsVector::kStaticOffsetsVectorSize);
11401 __ j(above, &runtime); 11405 __ j(above, &runtime);
11402 11406
11403 // ecx: RegExp data (FixedArray) 11407 // ecx: RegExp data (FixedArray)
11404 // edx: Number of capture registers 11408 // edx: Number of capture registers
11405 // Check that the second argument is a string. 11409 // Check that the second argument is a string.
11406 __ mov(eax, Operand(esp, kSubjectOffset)); 11410 __ mov(eax, Operand(esp, kSubjectOffset));
11407 __ test(eax, Immediate(kSmiTagMask)); 11411 __ test(eax, Immediate(kSmiTagMask));
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
11445 11449
11446 // ecx: RegExp data (FixedArray) 11450 // ecx: RegExp data (FixedArray)
11447 // Check the representation and encoding of the subject string. 11451 // Check the representation and encoding of the subject string.
11448 Label seq_ascii_string, seq_two_byte_string, check_code; 11452 Label seq_ascii_string, seq_two_byte_string, check_code;
11449 __ mov(eax, Operand(esp, kSubjectOffset)); 11453 __ mov(eax, Operand(esp, kSubjectOffset));
11450 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 11454 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
11451 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 11455 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
11452 // First check for flat two byte string. 11456 // First check for flat two byte string.
11453 __ and_(ebx, 11457 __ and_(ebx,
11454 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); 11458 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
11455 ASSERT_EQ(0, kStringTag | kSeqStringTag | kTwoByteStringTag); 11459 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
11456 __ j(zero, &seq_two_byte_string); 11460 __ j(zero, &seq_two_byte_string);
11457 // Any other flat string must be a flat ascii string. 11461 // Any other flat string must be a flat ascii string.
11458 __ test(Operand(ebx), 11462 __ test(Operand(ebx),
11459 Immediate(kIsNotStringMask | kStringRepresentationMask)); 11463 Immediate(kIsNotStringMask | kStringRepresentationMask));
11460 __ j(zero, &seq_ascii_string); 11464 __ j(zero, &seq_ascii_string);
11461 11465
11462 // Check for flat cons string. 11466 // Check for flat cons string.
11463 // A flat cons string is a cons string where the second part is the empty 11467 // A flat cons string is a cons string where the second part is the empty
11464 // string. In that case the subject string is just the first part of the cons 11468 // string. In that case the subject string is just the first part of the cons
11465 // string. Also in this case the first part of the cons string is known to be 11469 // string. Also in this case the first part of the cons string is known to be
11466 // a sequential string or an external string. 11470 // a sequential string or an external string.
11467 ASSERT(kExternalStringTag !=0); 11471 STATIC_ASSERT(kExternalStringTag != 0);
11468 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); 11472 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0);
11469 __ test(Operand(ebx), 11473 __ test(Operand(ebx),
11470 Immediate(kIsNotStringMask | kExternalStringTag)); 11474 Immediate(kIsNotStringMask | kExternalStringTag));
11471 __ j(not_zero, &runtime); 11475 __ j(not_zero, &runtime);
11472 // String is a cons string. 11476 // String is a cons string.
11473 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); 11477 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset));
11474 __ cmp(Operand(edx), Factory::empty_string()); 11478 __ cmp(Operand(edx), Factory::empty_string());
11475 __ j(not_equal, &runtime); 11479 __ j(not_equal, &runtime);
11476 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); 11480 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
11477 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 11481 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
11478 // String is a cons string with empty second part. 11482 // String is a cons string with empty second part.
11479 // eax: first part of cons string. 11483 // eax: first part of cons string.
11480 // ebx: map of first part of cons string. 11484 // ebx: map of first part of cons string.
11481 // Is first part a flat two byte string? 11485 // Is first part a flat two byte string?
11482 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), 11486 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
11483 kStringRepresentationMask | kStringEncodingMask); 11487 kStringRepresentationMask | kStringEncodingMask);
11484 ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag); 11488 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
11485 __ j(zero, &seq_two_byte_string); 11489 __ j(zero, &seq_two_byte_string);
11486 // Any other flat string must be ascii. 11490 // Any other flat string must be ascii.
11487 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), 11491 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
11488 kStringRepresentationMask); 11492 kStringRepresentationMask);
11489 __ j(not_zero, &runtime); 11493 __ j(not_zero, &runtime);
11490 11494
11491 __ bind(&seq_ascii_string); 11495 __ bind(&seq_ascii_string);
11492 // eax: subject string (flat ascii) 11496 // eax: subject string (flat ascii)
11493 // ecx: RegExp data (FixedArray) 11497 // ecx: RegExp data (FixedArray)
11494 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); 11498 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset));
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
11545 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); 11549 __ mov(edi, FieldOperand(eax, String::kLengthOffset));
11546 __ j(zero, &setup_two_byte); 11550 __ j(zero, &setup_two_byte);
11547 __ SmiUntag(edi); 11551 __ SmiUntag(edi);
11548 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); 11552 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize));
11549 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. 11553 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
11550 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); 11554 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
11551 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. 11555 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
11552 __ jmp(&setup_rest); 11556 __ jmp(&setup_rest);
11553 11557
11554 __ bind(&setup_two_byte); 11558 __ bind(&setup_two_byte);
11555 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); // edi is smi (powered by 2). 11559 STATIC_ASSERT(kSmiTag == 0);
11560 STATIC_ASSERT(kSmiTagSize == 1); // edi is smi (powered by 2).
11556 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqTwoByteString::kHeaderSize)); 11561 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqTwoByteString::kHeaderSize));
11557 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. 11562 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
11558 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); 11563 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
11559 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. 11564 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
11560 11565
11561 __ bind(&setup_rest); 11566 __ bind(&setup_rest);
11562 11567
11563 // Argument 2: Previous index. 11568 // Argument 2: Previous index.
11564 __ mov(Operand(esp, 1 * kPointerSize), ebx); 11569 __ mov(Operand(esp, 1 * kPointerSize), ebx);
11565 11570
(...skipping 27 matching lines...) Expand all
11593 // For failure and exception return null. 11598 // For failure and exception return null.
11594 __ mov(Operand(eax), Factory::null_value()); 11599 __ mov(Operand(eax), Factory::null_value());
11595 __ ret(4 * kPointerSize); 11600 __ ret(4 * kPointerSize);
11596 11601
11597 // Load RegExp data. 11602 // Load RegExp data.
11598 __ bind(&success); 11603 __ bind(&success);
11599 __ mov(eax, Operand(esp, kJSRegExpOffset)); 11604 __ mov(eax, Operand(esp, kJSRegExpOffset));
11600 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); 11605 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
11601 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); 11606 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
11602 // Calculate number of capture registers (number_of_captures + 1) * 2. 11607 // Calculate number of capture registers (number_of_captures + 1) * 2.
11603 ASSERT_EQ(0, kSmiTag); 11608 STATIC_ASSERT(kSmiTag == 0);
11604 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 11609 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
11605 __ add(Operand(edx), Immediate(2)); // edx was a smi. 11610 __ add(Operand(edx), Immediate(2)); // edx was a smi.
11606 11611
11607 // edx: Number of capture registers 11612 // edx: Number of capture registers
11608 // Load last_match_info which is still known to be a fast case JSArray. 11613 // Load last_match_info which is still known to be a fast case JSArray.
11609 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); 11614 __ mov(eax, Operand(esp, kLastMatchInfoOffset));
11610 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); 11615 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset));
11611 11616
11612 // ebx: last_match_info backing store (FixedArray) 11617 // ebx: last_match_info backing store (FixedArray)
11613 // edx: number of capture registers 11618 // edx: number of capture registers
11614 // Store the capture count. 11619 // Store the capture count.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
11689 // number string cache for smis is just the smi value, and the hash for 11694 // number string cache for smis is just the smi value, and the hash for
11690 // doubles is the xor of the upper and lower words. See 11695 // doubles is the xor of the upper and lower words. See
11691 // Heap::GetNumberStringCache. 11696 // Heap::GetNumberStringCache.
11692 Label smi_hash_calculated; 11697 Label smi_hash_calculated;
11693 Label load_result_from_cache; 11698 Label load_result_from_cache;
11694 if (object_is_smi) { 11699 if (object_is_smi) {
11695 __ mov(scratch, object); 11700 __ mov(scratch, object);
11696 __ SmiUntag(scratch); 11701 __ SmiUntag(scratch);
11697 } else { 11702 } else {
11698 Label not_smi, hash_calculated; 11703 Label not_smi, hash_calculated;
11699 ASSERT(kSmiTag == 0); 11704 STATIC_ASSERT(kSmiTag == 0);
11700 __ test(object, Immediate(kSmiTagMask)); 11705 __ test(object, Immediate(kSmiTagMask));
11701 __ j(not_zero, &not_smi); 11706 __ j(not_zero, &not_smi);
11702 __ mov(scratch, object); 11707 __ mov(scratch, object);
11703 __ SmiUntag(scratch); 11708 __ SmiUntag(scratch);
11704 __ jmp(&smi_hash_calculated); 11709 __ jmp(&smi_hash_calculated);
11705 __ bind(&not_smi); 11710 __ bind(&not_smi);
11706 __ cmp(FieldOperand(object, HeapObject::kMapOffset), 11711 __ cmp(FieldOperand(object, HeapObject::kMapOffset),
11707 Factory::heap_number_map()); 11712 Factory::heap_number_map());
11708 __ j(not_equal, not_found); 11713 __ j(not_equal, not_found);
11709 ASSERT_EQ(8, kDoubleSize); 11714 STATIC_ASSERT(8 == kDoubleSize);
11710 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); 11715 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
11711 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); 11716 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
11712 // Object is heap number and hash is now in scratch. Calculate cache index. 11717 // Object is heap number and hash is now in scratch. Calculate cache index.
11713 __ and_(scratch, Operand(mask)); 11718 __ and_(scratch, Operand(mask));
11714 Register index = scratch; 11719 Register index = scratch;
11715 Register probe = mask; 11720 Register probe = mask;
11716 __ mov(probe, 11721 __ mov(probe,
11717 FieldOperand(number_string_cache, 11722 FieldOperand(number_string_cache,
11718 index, 11723 index,
11719 times_twice_pointer_size, 11724 times_twice_pointer_size,
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
11830 // It is a heap number, so return non-equal if it's NaN and equal if 11835 // It is a heap number, so return non-equal if it's NaN and equal if
11831 // it's not NaN. 11836 // it's not NaN.
11832 // The representation of NaN values has all exponent bits (52..62) set, 11837 // The representation of NaN values has all exponent bits (52..62) set,
11833 // and not all mantissa bits (0..51) clear. 11838 // and not all mantissa bits (0..51) clear.
11834 // We only accept QNaNs, which have bit 51 set. 11839 // We only accept QNaNs, which have bit 51 set.
11835 // Read top bits of double representation (second word of value). 11840 // Read top bits of double representation (second word of value).
11836 11841
11837 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., 11842 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e.,
11838 // all bits in the mask are set. We only need to check the word 11843 // all bits in the mask are set. We only need to check the word
11839 // that contains the exponent and high bit of the mantissa. 11844 // that contains the exponent and high bit of the mantissa.
11840 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); 11845 STATIC_ASSERT(((kQuietNaNHighBitsMask << 1) & 0x80000000u) != 0);
11841 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); 11846 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset));
11842 __ xor_(eax, Operand(eax)); 11847 __ xor_(eax, Operand(eax));
11843 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost 11848 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost
11844 // bits. 11849 // bits.
11845 __ add(edx, Operand(edx)); 11850 __ add(edx, Operand(edx));
11846 __ cmp(edx, kQuietNaNHighBitsMask << 1); 11851 __ cmp(edx, kQuietNaNHighBitsMask << 1);
11847 if (cc_ == equal) { 11852 if (cc_ == equal) {
11848 ASSERT_NE(1, EQUAL); 11853 STATIC_ASSERT(EQUAL != 1);
11849 __ setcc(above_equal, eax); 11854 __ setcc(above_equal, eax);
11850 __ ret(0); 11855 __ ret(0);
11851 } else { 11856 } else {
11852 Label nan; 11857 Label nan;
11853 __ j(above_equal, &nan); 11858 __ j(above_equal, &nan);
11854 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 11859 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
11855 __ ret(0); 11860 __ ret(0);
11856 __ bind(&nan); 11861 __ bind(&nan);
11857 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); 11862 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_))));
11858 __ ret(0); 11863 __ ret(0);
11859 } 11864 }
11860 } 11865 }
11861 11866
11862 __ bind(&not_identical); 11867 __ bind(&not_identical);
11863 } 11868 }
11864 11869
11865 // Strict equality can quickly decide whether objects are equal. 11870 // Strict equality can quickly decide whether objects are equal.
11866 // Non-strict object equality is slower, so it is handled later in the stub. 11871 // Non-strict object equality is slower, so it is handled later in the stub.
11867 if (cc_ == equal && strict_) { 11872 if (cc_ == equal && strict_) {
11868 Label slow; // Fallthrough label. 11873 Label slow; // Fallthrough label.
11869 Label not_smis; 11874 Label not_smis;
11870 // If we're doing a strict equality comparison, we don't have to do 11875 // If we're doing a strict equality comparison, we don't have to do
11871 // type conversion, so we generate code to do fast comparison for objects 11876 // type conversion, so we generate code to do fast comparison for objects
11872 // and oddballs. Non-smi numbers and strings still go through the usual 11877 // and oddballs. Non-smi numbers and strings still go through the usual
11873 // slow-case code. 11878 // slow-case code.
11874 // If either is a Smi (we know that not both are), then they can only 11879 // If either is a Smi (we know that not both are), then they can only
11875 // be equal if the other is a HeapNumber. If so, use the slow case. 11880 // be equal if the other is a HeapNumber. If so, use the slow case.
11876 ASSERT_EQ(0, kSmiTag); 11881 STATIC_ASSERT(kSmiTag == 0);
11877 ASSERT_EQ(0, Smi::FromInt(0)); 11882 ASSERT_EQ(0, Smi::FromInt(0));
11878 __ mov(ecx, Immediate(kSmiTagMask)); 11883 __ mov(ecx, Immediate(kSmiTagMask));
11879 __ and_(ecx, Operand(eax)); 11884 __ and_(ecx, Operand(eax));
11880 __ test(ecx, Operand(edx)); 11885 __ test(ecx, Operand(edx));
11881 __ j(not_zero, &not_smis); 11886 __ j(not_zero, &not_smis);
11882 // One operand is a smi. 11887 // One operand is a smi.
11883 11888
11884 // Check whether the non-smi is a heap number. 11889 // Check whether the non-smi is a heap number.
11885 ASSERT_EQ(1, kSmiTagMask); 11890 STATIC_ASSERT(kSmiTagMask == 1);
11886 // ecx still holds eax & kSmiTag, which is either zero or one. 11891 // ecx still holds eax & kSmiTag, which is either zero or one.
11887 __ sub(Operand(ecx), Immediate(0x01)); 11892 __ sub(Operand(ecx), Immediate(0x01));
11888 __ mov(ebx, edx); 11893 __ mov(ebx, edx);
11889 __ xor_(ebx, Operand(eax)); 11894 __ xor_(ebx, Operand(eax));
11890 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. 11895 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx.
11891 __ xor_(ebx, Operand(eax)); 11896 __ xor_(ebx, Operand(eax));
11892 // if eax was smi, ebx is now edx, else eax. 11897 // if eax was smi, ebx is now edx, else eax.
11893 11898
11894 // Check if the non-smi operand is a heap number. 11899 // Check if the non-smi operand is a heap number.
11895 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 11900 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
11896 Immediate(Factory::heap_number_map())); 11901 Immediate(Factory::heap_number_map()));
11897 // If heap number, handle it in the slow case. 11902 // If heap number, handle it in the slow case.
11898 __ j(equal, &slow); 11903 __ j(equal, &slow);
11899 // Return non-equal (ebx is not zero) 11904 // Return non-equal (ebx is not zero)
11900 __ mov(eax, ebx); 11905 __ mov(eax, ebx);
11901 __ ret(0); 11906 __ ret(0);
11902 11907
11903 __ bind(&not_smis); 11908 __ bind(&not_smis);
11904 // If either operand is a JSObject or an oddball value, then they are not 11909 // If either operand is a JSObject or an oddball value, then they are not
11905 // equal since their pointers are different 11910 // equal since their pointers are different
11906 // There is no test for undetectability in strict equality. 11911 // There is no test for undetectability in strict equality.
11907 11912
11908 // Get the type of the first operand. 11913 // Get the type of the first operand.
11909 // If the first object is a JS object, we have done pointer comparison. 11914 // If the first object is a JS object, we have done pointer comparison.
11910 Label first_non_object; 11915 Label first_non_object;
11911 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 11916 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
11912 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 11917 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
11913 __ j(below, &first_non_object); 11918 __ j(below, &first_non_object);
11914 11919
11915 // Return non-zero (eax is not zero) 11920 // Return non-zero (eax is not zero)
11916 Label return_not_equal; 11921 Label return_not_equal;
11917 ASSERT(kHeapObjectTag != 0); 11922 STATIC_ASSERT(kHeapObjectTag != 0);
11918 __ bind(&return_not_equal); 11923 __ bind(&return_not_equal);
11919 __ ret(0); 11924 __ ret(0);
11920 11925
11921 __ bind(&first_non_object); 11926 __ bind(&first_non_object);
11922 // Check for oddballs: true, false, null, undefined. 11927 // Check for oddballs: true, false, null, undefined.
11923 __ CmpInstanceType(ecx, ODDBALL_TYPE); 11928 __ CmpInstanceType(ecx, ODDBALL_TYPE);
11924 __ j(equal, &return_not_equal); 11929 __ j(equal, &return_not_equal);
11925 11930
11926 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx); 11931 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx);
11927 __ j(above_equal, &return_not_equal); 11932 __ j(above_equal, &return_not_equal);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
12027 __ bind(&check_unequal_objects); 12032 __ bind(&check_unequal_objects);
12028 if (cc_ == equal && !strict_) { 12033 if (cc_ == equal && !strict_) {
12029 // Non-strict equality. Objects are unequal if 12034 // Non-strict equality. Objects are unequal if
12030 // they are both JSObjects and not undetectable, 12035 // they are both JSObjects and not undetectable,
12031 // and their pointers are different. 12036 // and their pointers are different.
12032 Label not_both_objects; 12037 Label not_both_objects;
12033 Label return_unequal; 12038 Label return_unequal;
12034 // At most one is a smi, so we can test for smi by adding the two. 12039 // At most one is a smi, so we can test for smi by adding the two.
12035 // A smi plus a heap object has the low bit set, a heap object plus 12040 // A smi plus a heap object has the low bit set, a heap object plus
12036 // a heap object has the low bit clear. 12041 // a heap object has the low bit clear.
12037 ASSERT_EQ(0, kSmiTag); 12042 STATIC_ASSERT(kSmiTag == 0);
12038 ASSERT_EQ(1, kSmiTagMask); 12043 STATIC_ASSERT(kSmiTagMask == 1);
12039 __ lea(ecx, Operand(eax, edx, times_1, 0)); 12044 __ lea(ecx, Operand(eax, edx, times_1, 0));
12040 __ test(ecx, Immediate(kSmiTagMask)); 12045 __ test(ecx, Immediate(kSmiTagMask));
12041 __ j(not_zero, &not_both_objects); 12046 __ j(not_zero, &not_both_objects);
12042 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 12047 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
12043 __ j(below, &not_both_objects); 12048 __ j(below, &not_both_objects);
12044 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx); 12049 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx);
12045 __ j(below, &not_both_objects); 12050 __ j(below, &not_both_objects);
12046 // We do not bail out after this point. Both are JSObjects, and 12051 // We do not bail out after this point. Both are JSObjects, and
12047 // they are equal if and only if both are undetectable. 12052 // they are equal if and only if both are undetectable.
12048 // The and of the undetectable flags is 1 if and only if they are equal. 12053 // The and of the undetectable flags is 1 if and only if they are equal.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
12168 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 12173 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
12169 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 12174 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
12170 __ jmp(adaptor, RelocInfo::CODE_TARGET); 12175 __ jmp(adaptor, RelocInfo::CODE_TARGET);
12171 } 12176 }
12172 12177
12173 12178
12174 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { 12179 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
12175 // eax holds the exception. 12180 // eax holds the exception.
12176 12181
12177 // Adjust this code if not the case. 12182 // Adjust this code if not the case.
12178 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 12183 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
12179 12184
12180 // Drop the sp to the top of the handler. 12185 // Drop the sp to the top of the handler.
12181 ExternalReference handler_address(Top::k_handler_address); 12186 ExternalReference handler_address(Top::k_handler_address);
12182 __ mov(esp, Operand::StaticVariable(handler_address)); 12187 __ mov(esp, Operand::StaticVariable(handler_address));
12183 12188
12184 // Restore next handler and frame pointer, discard handler state. 12189 // Restore next handler and frame pointer, discard handler state.
12185 ASSERT(StackHandlerConstants::kNextOffset == 0); 12190 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12186 __ pop(Operand::StaticVariable(handler_address)); 12191 __ pop(Operand::StaticVariable(handler_address));
12187 ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); 12192 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
12188 __ pop(ebp); 12193 __ pop(ebp);
12189 __ pop(edx); // Remove state. 12194 __ pop(edx); // Remove state.
12190 12195
12191 // Before returning we restore the context from the frame pointer if 12196 // Before returning we restore the context from the frame pointer if
12192 // not NULL. The frame pointer is NULL in the exception handler of 12197 // not NULL. The frame pointer is NULL in the exception handler of
12193 // a JS entry frame. 12198 // a JS entry frame.
12194 __ xor_(esi, Operand(esi)); // Tentatively set context pointer to NULL. 12199 __ xor_(esi, Operand(esi)); // Tentatively set context pointer to NULL.
12195 Label skip; 12200 Label skip;
12196 __ cmp(ebp, 0); 12201 __ cmp(ebp, 0);
12197 __ j(equal, &skip, not_taken); 12202 __ j(equal, &skip, not_taken);
12198 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 12203 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
12199 __ bind(&skip); 12204 __ bind(&skip);
12200 12205
12201 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); 12206 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
12202 __ ret(0); 12207 __ ret(0);
12203 } 12208 }
12204 12209
12205 12210
12206 // If true, a Handle<T> passed by value is passed and returned by 12211 // If true, a Handle<T> passed by value is passed and returned by
12207 // using the location_ field directly. If false, it is passed and 12212 // using the location_ field directly. If false, it is passed and
12208 // returned as a pointer to a handle. 12213 // returned as a pointer to a handle.
12209 #ifdef USING_BSD_ABI 12214 #ifdef USING_BSD_ABI
12210 static const bool kPassHandlesDirectly = true; 12215 static const bool kPassHandlesDirectly = true;
12211 #else 12216 #else
12212 static const bool kPassHandlesDirectly = false; 12217 static const bool kPassHandlesDirectly = false;
12213 #endif 12218 #endif
12214 12219
12215 12220
12216 void ApiGetterEntryStub::Generate(MacroAssembler* masm) { 12221 void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
12217 Label get_result; 12222 Label get_result;
12218 Label prologue; 12223 Label prologue;
12219 Label promote_scheduled_exception; 12224 Label promote_scheduled_exception;
12220 __ EnterApiExitFrame(ExitFrame::MODE_NORMAL, kStackSpace, kArgc); 12225 __ EnterApiExitFrame(ExitFrame::MODE_NORMAL, kStackSpace, kArgc);
12221 ASSERT_EQ(kArgc, 4); 12226 STATIC_ASSERT(kArgc == 4);
12222 if (kPassHandlesDirectly) { 12227 if (kPassHandlesDirectly) {
12223 // When handles as passed directly we don't have to allocate extra 12228 // When handles as passed directly we don't have to allocate extra
12224 // space for and pass an out parameter. 12229 // space for and pass an out parameter.
12225 __ mov(Operand(esp, 0 * kPointerSize), ebx); // name. 12230 __ mov(Operand(esp, 0 * kPointerSize), ebx); // name.
12226 __ mov(Operand(esp, 1 * kPointerSize), eax); // arguments pointer. 12231 __ mov(Operand(esp, 1 * kPointerSize), eax); // arguments pointer.
12227 } else { 12232 } else {
12228 // The function expects three arguments to be passed but we allocate 12233 // The function expects three arguments to be passed but we allocate
12229 // four to get space for the output cell. The argument slots are filled 12234 // four to get space for the output cell. The argument slots are filled
12230 // as follows: 12235 // as follows:
12231 // 12236 //
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
12326 if (FLAG_debug_code) { 12331 if (FLAG_debug_code) {
12327 Label okay; 12332 Label okay;
12328 __ cmp(eax, Factory::the_hole_value()); 12333 __ cmp(eax, Factory::the_hole_value());
12329 __ j(not_equal, &okay); 12334 __ j(not_equal, &okay);
12330 __ int3(); 12335 __ int3();
12331 __ bind(&okay); 12336 __ bind(&okay);
12332 } 12337 }
12333 12338
12334 // Check for failure result. 12339 // Check for failure result.
12335 Label failure_returned; 12340 Label failure_returned;
12336 ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 12341 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
12337 __ lea(ecx, Operand(eax, 1)); 12342 __ lea(ecx, Operand(eax, 1));
12338 // Lower 2 bits of ecx are 0 iff eax has failure tag. 12343 // Lower 2 bits of ecx are 0 iff eax has failure tag.
12339 __ test(ecx, Immediate(kFailureTagMask)); 12344 __ test(ecx, Immediate(kFailureTagMask));
12340 __ j(zero, &failure_returned, not_taken); 12345 __ j(zero, &failure_returned, not_taken);
12341 12346
12342 // Exit the JavaScript to C++ exit frame. 12347 // Exit the JavaScript to C++ exit frame.
12343 __ LeaveExitFrame(mode_); 12348 __ LeaveExitFrame(mode_);
12344 __ ret(0); 12349 __ ret(0);
12345 12350
12346 // Handling of failure. 12351 // Handling of failure.
12347 __ bind(&failure_returned); 12352 __ bind(&failure_returned);
12348 12353
12349 Label retry; 12354 Label retry;
12350 // If the returned exception is RETRY_AFTER_GC continue at retry label 12355 // If the returned exception is RETRY_AFTER_GC continue at retry label
12351 ASSERT(Failure::RETRY_AFTER_GC == 0); 12356 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
12352 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); 12357 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
12353 __ j(zero, &retry, taken); 12358 __ j(zero, &retry, taken);
12354 12359
12355 // Special handling of out of memory exceptions. 12360 // Special handling of out of memory exceptions.
12356 __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); 12361 __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
12357 __ j(equal, throw_out_of_memory_exception); 12362 __ j(equal, throw_out_of_memory_exception);
12358 12363
12359 // Retrieve the pending exception and clear the variable. 12364 // Retrieve the pending exception and clear the variable.
12360 ExternalReference pending_exception_address(Top::k_pending_exception_address); 12365 ExternalReference pending_exception_address(Top::k_pending_exception_address);
12361 __ mov(eax, Operand::StaticVariable(pending_exception_address)); 12366 __ mov(eax, Operand::StaticVariable(pending_exception_address));
(...skipping 10 matching lines...) Expand all
12372 __ jmp(throw_normal_exception); 12377 __ jmp(throw_normal_exception);
12373 12378
12374 // Retry. 12379 // Retry.
12375 __ bind(&retry); 12380 __ bind(&retry);
12376 } 12381 }
12377 12382
12378 12383
12379 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, 12384 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
12380 UncatchableExceptionType type) { 12385 UncatchableExceptionType type) {
12381 // Adjust this code if not the case. 12386 // Adjust this code if not the case.
12382 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 12387 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
12383 12388
12384 // Drop sp to the top stack handler. 12389 // Drop sp to the top stack handler.
12385 ExternalReference handler_address(Top::k_handler_address); 12390 ExternalReference handler_address(Top::k_handler_address);
12386 __ mov(esp, Operand::StaticVariable(handler_address)); 12391 __ mov(esp, Operand::StaticVariable(handler_address));
12387 12392
12388 // Unwind the handlers until the ENTRY handler is found. 12393 // Unwind the handlers until the ENTRY handler is found.
12389 Label loop, done; 12394 Label loop, done;
12390 __ bind(&loop); 12395 __ bind(&loop);
12391 // Load the type of the current stack handler. 12396 // Load the type of the current stack handler.
12392 const int kStateOffset = StackHandlerConstants::kStateOffset; 12397 const int kStateOffset = StackHandlerConstants::kStateOffset;
12393 __ cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY)); 12398 __ cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY));
12394 __ j(equal, &done); 12399 __ j(equal, &done);
12395 // Fetch the next handler in the list. 12400 // Fetch the next handler in the list.
12396 const int kNextOffset = StackHandlerConstants::kNextOffset; 12401 const int kNextOffset = StackHandlerConstants::kNextOffset;
12397 __ mov(esp, Operand(esp, kNextOffset)); 12402 __ mov(esp, Operand(esp, kNextOffset));
12398 __ jmp(&loop); 12403 __ jmp(&loop);
12399 __ bind(&done); 12404 __ bind(&done);
12400 12405
12401 // Set the top handler address to next handler past the current ENTRY handler. 12406 // Set the top handler address to next handler past the current ENTRY handler.
12402 ASSERT(StackHandlerConstants::kNextOffset == 0); 12407 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
12403 __ pop(Operand::StaticVariable(handler_address)); 12408 __ pop(Operand::StaticVariable(handler_address));
12404 12409
12405 if (type == OUT_OF_MEMORY) { 12410 if (type == OUT_OF_MEMORY) {
12406 // Set external caught exception to false. 12411 // Set external caught exception to false.
12407 ExternalReference external_caught(Top::k_external_caught_exception_address); 12412 ExternalReference external_caught(Top::k_external_caught_exception_address);
12408 __ mov(eax, false); 12413 __ mov(eax, false);
12409 __ mov(Operand::StaticVariable(external_caught), eax); 12414 __ mov(Operand::StaticVariable(external_caught), eax);
12410 12415
12411 // Set pending exception and eax to out of memory exception. 12416 // Set pending exception and eax to out of memory exception.
12412 ExternalReference pending_exception(Top::k_pending_exception_address); 12417 ExternalReference pending_exception(Top::k_pending_exception_address);
12413 __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); 12418 __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
12414 __ mov(Operand::StaticVariable(pending_exception), eax); 12419 __ mov(Operand::StaticVariable(pending_exception), eax);
12415 } 12420 }
12416 12421
12417 // Clear the context pointer. 12422 // Clear the context pointer.
12418 __ xor_(esi, Operand(esi)); 12423 __ xor_(esi, Operand(esi));
12419 12424
12420 // Restore fp from handler and discard handler state. 12425 // Restore fp from handler and discard handler state.
12421 ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); 12426 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
12422 __ pop(ebp); 12427 __ pop(ebp);
12423 __ pop(edx); // State. 12428 __ pop(edx); // State.
12424 12429
12425 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); 12430 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
12426 __ ret(0); 12431 __ ret(0);
12427 } 12432 }
12428 12433
12429 12434
12430 void CEntryStub::Generate(MacroAssembler* masm) { 12435 void CEntryStub::Generate(MacroAssembler* masm) {
12431 // eax: number of arguments including receiver 12436 // eax: number of arguments including receiver
12432 // ebx: pointer to C function (C callee-saved) 12437 // ebx: pointer to C function (C callee-saved)
12433 // ebp: frame pointer (restored after C call) 12438 // ebp: frame pointer (restored after C call)
12434 // esp: stack pointer (restored after C call) 12439 // esp: stack pointer (restored after C call)
12435 // esi: current context (C callee-saved) 12440 // esi: current context (C callee-saved)
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
12726 12731
12727 // ------------------------------------------------------------------------- 12732 // -------------------------------------------------------------------------
12728 // StringCharCodeAtGenerator 12733 // StringCharCodeAtGenerator
12729 12734
12730 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 12735 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
12731 Label flat_string; 12736 Label flat_string;
12732 Label ascii_string; 12737 Label ascii_string;
12733 Label got_char_code; 12738 Label got_char_code;
12734 12739
12735 // If the receiver is a smi trigger the non-string case. 12740 // If the receiver is a smi trigger the non-string case.
12736 ASSERT(kSmiTag == 0); 12741 STATIC_ASSERT(kSmiTag == 0);
12737 __ test(object_, Immediate(kSmiTagMask)); 12742 __ test(object_, Immediate(kSmiTagMask));
12738 __ j(zero, receiver_not_string_); 12743 __ j(zero, receiver_not_string_);
12739 12744
12740 // Fetch the instance type of the receiver into result register. 12745 // Fetch the instance type of the receiver into result register.
12741 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 12746 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
12742 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 12747 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
12743 // If the receiver is not a string trigger the non-string case. 12748 // If the receiver is not a string trigger the non-string case.
12744 __ test(result_, Immediate(kIsNotStringMask)); 12749 __ test(result_, Immediate(kIsNotStringMask));
12745 __ j(not_zero, receiver_not_string_); 12750 __ j(not_zero, receiver_not_string_);
12746 12751
12747 // If the index is non-smi trigger the non-smi case. 12752 // If the index is non-smi trigger the non-smi case.
12748 ASSERT(kSmiTag == 0); 12753 STATIC_ASSERT(kSmiTag == 0);
12749 __ test(index_, Immediate(kSmiTagMask)); 12754 __ test(index_, Immediate(kSmiTagMask));
12750 __ j(not_zero, &index_not_smi_); 12755 __ j(not_zero, &index_not_smi_);
12751 12756
12752 // Put smi-tagged index into scratch register. 12757 // Put smi-tagged index into scratch register.
12753 __ mov(scratch_, index_); 12758 __ mov(scratch_, index_);
12754 __ bind(&got_smi_index_); 12759 __ bind(&got_smi_index_);
12755 12760
12756 // Check for index out of range. 12761 // Check for index out of range.
12757 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset)); 12762 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset));
12758 __ j(above_equal, index_out_of_range_); 12763 __ j(above_equal, index_out_of_range_);
12759 12764
12760 // We need special handling for non-flat strings. 12765 // We need special handling for non-flat strings.
12761 ASSERT(kSeqStringTag == 0); 12766 STATIC_ASSERT(kSeqStringTag == 0);
12762 __ test(result_, Immediate(kStringRepresentationMask)); 12767 __ test(result_, Immediate(kStringRepresentationMask));
12763 __ j(zero, &flat_string); 12768 __ j(zero, &flat_string);
12764 12769
12765 // Handle non-flat strings. 12770 // Handle non-flat strings.
12766 __ test(result_, Immediate(kIsConsStringMask)); 12771 __ test(result_, Immediate(kIsConsStringMask));
12767 __ j(zero, &call_runtime_); 12772 __ j(zero, &call_runtime_);
12768 12773
12769 // ConsString. 12774 // ConsString.
12770 // Check whether the right hand side is the empty string (i.e. if 12775 // Check whether the right hand side is the empty string (i.e. if
12771 // this is really a flat string in a cons string). If that is not 12776 // this is really a flat string in a cons string). If that is not
12772 // the case we would rather go to the runtime system now to flatten 12777 // the case we would rather go to the runtime system now to flatten
12773 // the string. 12778 // the string.
12774 __ cmp(FieldOperand(object_, ConsString::kSecondOffset), 12779 __ cmp(FieldOperand(object_, ConsString::kSecondOffset),
12775 Immediate(Factory::empty_string())); 12780 Immediate(Factory::empty_string()));
12776 __ j(not_equal, &call_runtime_); 12781 __ j(not_equal, &call_runtime_);
12777 // Get the first of the two strings and load its instance type. 12782 // Get the first of the two strings and load its instance type.
12778 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset)); 12783 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset));
12779 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 12784 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
12780 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 12785 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
12781 // If the first cons component is also non-flat, then go to runtime. 12786 // If the first cons component is also non-flat, then go to runtime.
12782 ASSERT(kSeqStringTag == 0); 12787 STATIC_ASSERT(kSeqStringTag == 0);
12783 __ test(result_, Immediate(kStringRepresentationMask)); 12788 __ test(result_, Immediate(kStringRepresentationMask));
12784 __ j(not_zero, &call_runtime_); 12789 __ j(not_zero, &call_runtime_);
12785 12790
12786 // Check for 1-byte or 2-byte string. 12791 // Check for 1-byte or 2-byte string.
12787 __ bind(&flat_string); 12792 __ bind(&flat_string);
12788 ASSERT(kAsciiStringTag != 0); 12793 STATIC_ASSERT(kAsciiStringTag != 0);
12789 __ test(result_, Immediate(kStringEncodingMask)); 12794 __ test(result_, Immediate(kStringEncodingMask));
12790 __ j(not_zero, &ascii_string); 12795 __ j(not_zero, &ascii_string);
12791 12796
12792 // 2-byte string. 12797 // 2-byte string.
12793 // Load the 2-byte character code into the result register. 12798 // Load the 2-byte character code into the result register.
12794 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 12799 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
12795 __ movzx_w(result_, FieldOperand(object_, 12800 __ movzx_w(result_, FieldOperand(object_,
12796 scratch_, times_1, // Scratch is smi-tagged. 12801 scratch_, times_1, // Scratch is smi-tagged.
12797 SeqTwoByteString::kHeaderSize)); 12802 SeqTwoByteString::kHeaderSize));
12798 __ jmp(&got_char_code); 12803 __ jmp(&got_char_code);
12799 12804
12800 // ASCII string. 12805 // ASCII string.
12801 // Load the byte into the result register. 12806 // Load the byte into the result register.
12802 __ bind(&ascii_string); 12807 __ bind(&ascii_string);
12803 __ SmiUntag(scratch_); 12808 __ SmiUntag(scratch_);
12804 __ movzx_b(result_, FieldOperand(object_, 12809 __ movzx_b(result_, FieldOperand(object_,
(...skipping 29 matching lines...) Expand all
12834 // have a chance to overwrite it. 12839 // have a chance to overwrite it.
12835 __ mov(scratch_, eax); 12840 __ mov(scratch_, eax);
12836 } 12841 }
12837 __ pop(index_); 12842 __ pop(index_);
12838 __ pop(object_); 12843 __ pop(object_);
12839 // Reload the instance type. 12844 // Reload the instance type.
12840 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 12845 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
12841 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 12846 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
12842 call_helper.AfterCall(masm); 12847 call_helper.AfterCall(masm);
12843 // If index is still not a smi, it must be out of range. 12848 // If index is still not a smi, it must be out of range.
12844 ASSERT(kSmiTag == 0); 12849 STATIC_ASSERT(kSmiTag == 0);
12845 __ test(scratch_, Immediate(kSmiTagMask)); 12850 __ test(scratch_, Immediate(kSmiTagMask));
12846 __ j(not_zero, index_out_of_range_); 12851 __ j(not_zero, index_out_of_range_);
12847 // Otherwise, return to the fast path. 12852 // Otherwise, return to the fast path.
12848 __ jmp(&got_smi_index_); 12853 __ jmp(&got_smi_index_);
12849 12854
12850 // Call runtime. We get here when the receiver is a string and the 12855 // Call runtime. We get here when the receiver is a string and the
12851 // index is a number, but the code of getting the actual character 12856 // index is a number, but the code of getting the actual character
12852 // is too complex (e.g., when the string needs to be flattened). 12857 // is too complex (e.g., when the string needs to be flattened).
12853 __ bind(&call_runtime_); 12858 __ bind(&call_runtime_);
12854 call_helper.BeforeCall(masm); 12859 call_helper.BeforeCall(masm);
12855 __ push(object_); 12860 __ push(object_);
12856 __ push(index_); 12861 __ push(index_);
12857 __ CallRuntime(Runtime::kStringCharCodeAt, 2); 12862 __ CallRuntime(Runtime::kStringCharCodeAt, 2);
12858 if (!result_.is(eax)) { 12863 if (!result_.is(eax)) {
12859 __ mov(result_, eax); 12864 __ mov(result_, eax);
12860 } 12865 }
12861 call_helper.AfterCall(masm); 12866 call_helper.AfterCall(masm);
12862 __ jmp(&exit_); 12867 __ jmp(&exit_);
12863 12868
12864 __ Abort("Unexpected fallthrough from CharCodeAt slow case"); 12869 __ Abort("Unexpected fallthrough from CharCodeAt slow case");
12865 } 12870 }
12866 12871
12867 12872
12868 // ------------------------------------------------------------------------- 12873 // -------------------------------------------------------------------------
12869 // StringCharFromCodeGenerator 12874 // StringCharFromCodeGenerator
12870 12875
12871 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 12876 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
12872 // Fast case of Heap::LookupSingleCharacterStringFromCode. 12877 // Fast case of Heap::LookupSingleCharacterStringFromCode.
12873 ASSERT(kSmiTag == 0); 12878 STATIC_ASSERT(kSmiTag == 0);
12874 ASSERT(kSmiShiftSize == 0); 12879 STATIC_ASSERT(kSmiShiftSize == 0);
12875 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); 12880 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
12876 __ test(code_, 12881 __ test(code_,
12877 Immediate(kSmiTagMask | 12882 Immediate(kSmiTagMask |
12878 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); 12883 ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
12879 __ j(not_zero, &slow_case_, not_taken); 12884 __ j(not_zero, &slow_case_, not_taken);
12880 12885
12881 __ Set(result_, Immediate(Factory::single_character_string_cache())); 12886 __ Set(result_, Immediate(Factory::single_character_string_cache()));
12882 ASSERT(kSmiTag == 0); 12887 STATIC_ASSERT(kSmiTag == 0);
12883 ASSERT(kSmiTagSize == 1); 12888 STATIC_ASSERT(kSmiTagSize == 1);
12884 ASSERT(kSmiShiftSize == 0); 12889 STATIC_ASSERT(kSmiShiftSize == 0);
12885 // At this point code register contains smi tagged ascii char code. 12890 // At this point code register contains smi tagged ascii char code.
12886 __ mov(result_, FieldOperand(result_, 12891 __ mov(result_, FieldOperand(result_,
12887 code_, times_half_pointer_size, 12892 code_, times_half_pointer_size,
12888 FixedArray::kHeaderSize)); 12893 FixedArray::kHeaderSize));
12889 __ cmp(result_, Factory::undefined_value()); 12894 __ cmp(result_, Factory::undefined_value());
12890 __ j(equal, &slow_case_, not_taken); 12895 __ j(equal, &slow_case_, not_taken);
12891 __ bind(&exit_); 12896 __ bind(&exit_);
12892 } 12897 }
12893 12898
12894 12899
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
12946 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); 12951 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
12947 __ j(above_equal, &string_add_runtime); 12952 __ j(above_equal, &string_add_runtime);
12948 } 12953 }
12949 12954
12950 // Both arguments are strings. 12955 // Both arguments are strings.
12951 // eax: first string 12956 // eax: first string
12952 // edx: second string 12957 // edx: second string
12953 // Check if either of the strings are empty. In that case return the other. 12958 // Check if either of the strings are empty. In that case return the other.
12954 Label second_not_zero_length, both_not_zero_length; 12959 Label second_not_zero_length, both_not_zero_length;
12955 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); 12960 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
12956 ASSERT(kSmiTag == 0); 12961 STATIC_ASSERT(kSmiTag == 0);
12957 __ test(ecx, Operand(ecx)); 12962 __ test(ecx, Operand(ecx));
12958 __ j(not_zero, &second_not_zero_length); 12963 __ j(not_zero, &second_not_zero_length);
12959 // Second string is empty, result is first string which is already in eax. 12964 // Second string is empty, result is first string which is already in eax.
12960 __ IncrementCounter(&Counters::string_add_native, 1); 12965 __ IncrementCounter(&Counters::string_add_native, 1);
12961 __ ret(2 * kPointerSize); 12966 __ ret(2 * kPointerSize);
12962 __ bind(&second_not_zero_length); 12967 __ bind(&second_not_zero_length);
12963 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); 12968 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
12964 ASSERT(kSmiTag == 0); 12969 STATIC_ASSERT(kSmiTag == 0);
12965 __ test(ebx, Operand(ebx)); 12970 __ test(ebx, Operand(ebx));
12966 __ j(not_zero, &both_not_zero_length); 12971 __ j(not_zero, &both_not_zero_length);
12967 // First string is empty, result is second string which is in edx. 12972 // First string is empty, result is second string which is in edx.
12968 __ mov(eax, edx); 12973 __ mov(eax, edx);
12969 __ IncrementCounter(&Counters::string_add_native, 1); 12974 __ IncrementCounter(&Counters::string_add_native, 1);
12970 __ ret(2 * kPointerSize); 12975 __ ret(2 * kPointerSize);
12971 12976
12972 // Both strings are non-empty. 12977 // Both strings are non-empty.
12973 // eax: first string 12978 // eax: first string
12974 // ebx: length of first string as a smi 12979 // ebx: length of first string as a smi
12975 // ecx: length of second string as a smi 12980 // ecx: length of second string as a smi
12976 // edx: second string 12981 // edx: second string
12977 // Look at the length of the result of adding the two strings. 12982 // Look at the length of the result of adding the two strings.
12978 Label string_add_flat_result, longer_than_two; 12983 Label string_add_flat_result, longer_than_two;
12979 __ bind(&both_not_zero_length); 12984 __ bind(&both_not_zero_length);
12980 __ add(ebx, Operand(ecx)); 12985 __ add(ebx, Operand(ecx));
12981 ASSERT(Smi::kMaxValue == String::kMaxLength); 12986 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength);
12982 // Handle exceptionally long strings in the runtime system. 12987 // Handle exceptionally long strings in the runtime system.
12983 __ j(overflow, &string_add_runtime); 12988 __ j(overflow, &string_add_runtime);
12984 // Use the runtime system when adding two one character strings, as it 12989 // Use the runtime system when adding two one character strings, as it
12985 // contains optimizations for this specific case using the symbol table. 12990 // contains optimizations for this specific case using the symbol table.
12986 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2))); 12991 __ cmp(Operand(ebx), Immediate(Smi::FromInt(2)));
12987 __ j(not_equal, &longer_than_two); 12992 __ j(not_equal, &longer_than_two);
12988 12993
12989 // Check that both strings are non-external ascii strings. 12994 // Check that both strings are non-external ascii strings.
12990 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, 12995 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx,
12991 &string_add_runtime); 12996 &string_add_runtime);
(...skipping 20 matching lines...) Expand all
13012 __ j(below, &string_add_flat_result); 13017 __ j(below, &string_add_flat_result);
13013 13018
13014 // If result is not supposed to be flat allocate a cons string object. If both 13019 // If result is not supposed to be flat allocate a cons string object. If both
13015 // strings are ascii the result is an ascii cons string. 13020 // strings are ascii the result is an ascii cons string.
13016 Label non_ascii, allocated, ascii_data; 13021 Label non_ascii, allocated, ascii_data;
13017 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); 13022 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
13018 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); 13023 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
13019 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 13024 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
13020 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); 13025 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
13021 __ and_(ecx, Operand(edi)); 13026 __ and_(ecx, Operand(edi));
13022 ASSERT(kStringEncodingMask == kAsciiStringTag); 13027 STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag);
13023 __ test(ecx, Immediate(kAsciiStringTag)); 13028 __ test(ecx, Immediate(kAsciiStringTag));
13024 __ j(zero, &non_ascii); 13029 __ j(zero, &non_ascii);
13025 __ bind(&ascii_data); 13030 __ bind(&ascii_data);
13026 // Allocate an acsii cons string. 13031 // Allocate an acsii cons string.
13027 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime); 13032 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime);
13028 __ bind(&allocated); 13033 __ bind(&allocated);
13029 // Fill the fields of the cons string. 13034 // Fill the fields of the cons string.
13030 if (FLAG_debug_code) __ AbortIfNotSmi(ebx); 13035 if (FLAG_debug_code) __ AbortIfNotSmi(ebx);
13031 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); 13036 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
13032 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), 13037 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
13033 Immediate(String::kEmptyHashField)); 13038 Immediate(String::kEmptyHashField));
13034 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); 13039 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
13035 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); 13040 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
13036 __ mov(eax, ecx); 13041 __ mov(eax, ecx);
13037 __ IncrementCounter(&Counters::string_add_native, 1); 13042 __ IncrementCounter(&Counters::string_add_native, 1);
13038 __ ret(2 * kPointerSize); 13043 __ ret(2 * kPointerSize);
13039 __ bind(&non_ascii); 13044 __ bind(&non_ascii);
13040 // At least one of the strings is two-byte. Check whether it happens 13045 // At least one of the strings is two-byte. Check whether it happens
13041 // to contain only ascii characters. 13046 // to contain only ascii characters.
13042 // ecx: first instance type AND second instance type. 13047 // ecx: first instance type AND second instance type.
13043 // edi: second instance type. 13048 // edi: second instance type.
13044 __ test(ecx, Immediate(kAsciiDataHintMask)); 13049 __ test(ecx, Immediate(kAsciiDataHintMask));
13045 __ j(not_zero, &ascii_data); 13050 __ j(not_zero, &ascii_data);
13046 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 13051 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
13047 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 13052 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
13048 __ xor_(edi, Operand(ecx)); 13053 __ xor_(edi, Operand(ecx));
13049 ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); 13054 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
13050 __ and_(edi, kAsciiStringTag | kAsciiDataHintTag); 13055 __ and_(edi, kAsciiStringTag | kAsciiDataHintTag);
13051 __ cmp(edi, kAsciiStringTag | kAsciiDataHintTag); 13056 __ cmp(edi, kAsciiStringTag | kAsciiDataHintTag);
13052 __ j(equal, &ascii_data); 13057 __ j(equal, &ascii_data);
13053 // Allocate a two byte cons string. 13058 // Allocate a two byte cons string.
13054 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime); 13059 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime);
13055 __ jmp(&allocated); 13060 __ jmp(&allocated);
13056 13061
13057 // Handle creating a flat result. First check that both strings are not 13062 // Handle creating a flat result. First check that both strings are not
13058 // external strings. 13063 // external strings.
13059 // eax: first string 13064 // eax: first string
13060 // ebx: length of resulting flat string as a smi 13065 // ebx: length of resulting flat string as a smi
13061 // edx: second string 13066 // edx: second string
13062 __ bind(&string_add_flat_result); 13067 __ bind(&string_add_flat_result);
13063 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 13068 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
13064 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 13069 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
13065 __ and_(ecx, kStringRepresentationMask); 13070 __ and_(ecx, kStringRepresentationMask);
13066 __ cmp(ecx, kExternalStringTag); 13071 __ cmp(ecx, kExternalStringTag);
13067 __ j(equal, &string_add_runtime); 13072 __ j(equal, &string_add_runtime);
13068 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 13073 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
13069 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 13074 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
13070 __ and_(ecx, kStringRepresentationMask); 13075 __ and_(ecx, kStringRepresentationMask);
13071 __ cmp(ecx, kExternalStringTag); 13076 __ cmp(ecx, kExternalStringTag);
13072 __ j(equal, &string_add_runtime); 13077 __ j(equal, &string_add_runtime);
13073 // Now check if both strings are ascii strings. 13078 // Now check if both strings are ascii strings.
13074 // eax: first string 13079 // eax: first string
13075 // ebx: length of resulting flat string as a smi 13080 // ebx: length of resulting flat string as a smi
13076 // edx: second string 13081 // edx: second string
13077 Label non_ascii_string_add_flat_result; 13082 Label non_ascii_string_add_flat_result;
13078 ASSERT(kStringEncodingMask == kAsciiStringTag); 13083 STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag);
13079 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 13084 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
13080 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); 13085 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
13081 __ j(zero, &non_ascii_string_add_flat_result); 13086 __ j(zero, &non_ascii_string_add_flat_result);
13082 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 13087 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
13083 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); 13088 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
13084 __ j(zero, &string_add_runtime); 13089 __ j(zero, &string_add_runtime);
13085 13090
13086 __ bind(&make_flat_ascii_string); 13091 __ bind(&make_flat_ascii_string);
13087 // Both strings are ascii strings. As they are short they are both flat. 13092 // Both strings are ascii strings. As they are short they are both flat.
13088 // ebx: length of resulting flat string as a smi 13093 // ebx: length of resulting flat string as a smi
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
13187 __ j(not_zero, &loop); 13192 __ j(not_zero, &loop);
13188 } 13193 }
13189 13194
13190 13195
13191 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, 13196 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
13192 Register dest, 13197 Register dest,
13193 Register src, 13198 Register src,
13194 Register count, 13199 Register count,
13195 Register scratch, 13200 Register scratch,
13196 bool ascii) { 13201 bool ascii) {
13197 // Copy characters using rep movs of doublewords. Align destination on 4 byte 13202 // Copy characters using rep movs of doublewords.
13198 // boundary before starting rep movs. Copy remaining characters after running 13203 // The destination is aligned on a 4 byte boundary because we are
13199 // rep movs. 13204 // copying to the beginning of a newly allocated string.
13200 ASSERT(dest.is(edi)); // rep movs destination 13205 ASSERT(dest.is(edi)); // rep movs destination
13201 ASSERT(src.is(esi)); // rep movs source 13206 ASSERT(src.is(esi)); // rep movs source
13202 ASSERT(count.is(ecx)); // rep movs count 13207 ASSERT(count.is(ecx)); // rep movs count
13203 ASSERT(!scratch.is(dest)); 13208 ASSERT(!scratch.is(dest));
13204 ASSERT(!scratch.is(src)); 13209 ASSERT(!scratch.is(src));
13205 ASSERT(!scratch.is(count)); 13210 ASSERT(!scratch.is(count));
13206 13211
13207 // Nothing to do for zero characters. 13212 // Nothing to do for zero characters.
13208 Label done; 13213 Label done;
13209 __ test(count, Operand(count)); 13214 __ test(count, Operand(count));
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
13310 Label found_in_symbol_table; 13315 Label found_in_symbol_table;
13311 Label next_probe[kProbes], next_probe_pop_mask[kProbes]; 13316 Label next_probe[kProbes], next_probe_pop_mask[kProbes];
13312 for (int i = 0; i < kProbes; i++) { 13317 for (int i = 0; i < kProbes; i++) {
13313 // Calculate entry in symbol table. 13318 // Calculate entry in symbol table.
13314 __ mov(scratch, hash); 13319 __ mov(scratch, hash);
13315 if (i > 0) { 13320 if (i > 0) {
13316 __ add(Operand(scratch), Immediate(SymbolTable::GetProbeOffset(i))); 13321 __ add(Operand(scratch), Immediate(SymbolTable::GetProbeOffset(i)));
13317 } 13322 }
13318 __ and_(scratch, Operand(mask)); 13323 __ and_(scratch, Operand(mask));
13319 13324
13320 // Load the entry from the symble table. 13325 // Load the entry from the symbol table.
13321 Register candidate = scratch; // Scratch register contains candidate. 13326 Register candidate = scratch; // Scratch register contains candidate.
13322 ASSERT_EQ(1, SymbolTable::kEntrySize); 13327 STATIC_ASSERT(SymbolTable::kEntrySize == 1);
13323 __ mov(candidate, 13328 __ mov(candidate,
13324 FieldOperand(symbol_table, 13329 FieldOperand(symbol_table,
13325 scratch, 13330 scratch,
13326 times_pointer_size, 13331 times_pointer_size,
13327 SymbolTable::kElementsStartOffset)); 13332 SymbolTable::kElementsStartOffset));
13328 13333
13329 // If entry is undefined no string with this hash can be found. 13334 // If entry is undefined no string with this hash can be found.
13330 __ cmp(candidate, Factory::undefined_value()); 13335 __ cmp(candidate, Factory::undefined_value());
13331 __ j(equal, not_found); 13336 __ j(equal, not_found);
13332 13337
(...skipping 22 matching lines...) Expand all
13355 __ pop(mask); 13360 __ pop(mask);
13356 __ bind(&next_probe[i]); 13361 __ bind(&next_probe[i]);
13357 } 13362 }
13358 13363
13359 // No matching 2 character string found by probing. 13364 // No matching 2 character string found by probing.
13360 __ jmp(not_found); 13365 __ jmp(not_found);
13361 13366
13362 // Scratch register contains result when we fall through to here. 13367 // Scratch register contains result when we fall through to here.
13363 Register result = scratch; 13368 Register result = scratch;
13364 __ bind(&found_in_symbol_table); 13369 __ bind(&found_in_symbol_table);
13365 __ pop(mask); // Pop temporally saved mask from the stack. 13370 __ pop(mask); // Pop saved mask from the stack.
13366 if (!result.is(eax)) { 13371 if (!result.is(eax)) {
13367 __ mov(eax, result); 13372 __ mov(eax, result);
13368 } 13373 }
13369 } 13374 }
13370 13375
13371 13376
13372 void StringHelper::GenerateHashInit(MacroAssembler* masm, 13377 void StringHelper::GenerateHashInit(MacroAssembler* masm,
13373 Register hash, 13378 Register hash,
13374 Register character, 13379 Register character,
13375 Register scratch) { 13380 Register scratch) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
13430 Label runtime; 13435 Label runtime;
13431 13436
13432 // Stack frame on entry. 13437 // Stack frame on entry.
13433 // esp[0]: return address 13438 // esp[0]: return address
13434 // esp[4]: to 13439 // esp[4]: to
13435 // esp[8]: from 13440 // esp[8]: from
13436 // esp[12]: string 13441 // esp[12]: string
13437 13442
13438 // Make sure first argument is a string. 13443 // Make sure first argument is a string.
13439 __ mov(eax, Operand(esp, 3 * kPointerSize)); 13444 __ mov(eax, Operand(esp, 3 * kPointerSize));
13440 ASSERT_EQ(0, kSmiTag); 13445 STATIC_ASSERT(kSmiTag == 0);
13441 __ test(eax, Immediate(kSmiTagMask)); 13446 __ test(eax, Immediate(kSmiTagMask));
13442 __ j(zero, &runtime); 13447 __ j(zero, &runtime);
13443 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); 13448 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
13444 __ j(NegateCondition(is_string), &runtime); 13449 __ j(NegateCondition(is_string), &runtime);
13445 13450
13446 // eax: string 13451 // eax: string
13447 // ebx: instance type 13452 // ebx: instance type
13453
13448 // Calculate length of sub string using the smi values. 13454 // Calculate length of sub string using the smi values.
13449 Label result_longer_than_two; 13455 Label result_longer_than_two;
13450 __ mov(ecx, Operand(esp, 1 * kPointerSize)); // To index. 13456 __ mov(ecx, Operand(esp, 1 * kPointerSize)); // To index.
13451 __ test(ecx, Immediate(kSmiTagMask)); 13457 __ test(ecx, Immediate(kSmiTagMask));
13452 __ j(not_zero, &runtime); 13458 __ j(not_zero, &runtime);
13453 __ mov(edx, Operand(esp, 2 * kPointerSize)); // From index. 13459 __ mov(edx, Operand(esp, 2 * kPointerSize)); // From index.
13454 __ test(edx, Immediate(kSmiTagMask)); 13460 __ test(edx, Immediate(kSmiTagMask));
13455 __ j(not_zero, &runtime); 13461 __ j(not_zero, &runtime);
13456 __ sub(ecx, Operand(edx)); 13462 __ sub(ecx, Operand(edx));
13457 __ cmp(ecx, FieldOperand(eax, String::kLengthOffset)); 13463 __ cmp(ecx, FieldOperand(eax, String::kLengthOffset));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
13543 __ mov(edi, eax); 13549 __ mov(edi, eax);
13544 __ add(Operand(edi), 13550 __ add(Operand(edi),
13545 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 13551 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
13546 // Load string argument and locate character of sub string start. 13552 // Load string argument and locate character of sub string start.
13547 __ mov(esi, Operand(esp, 3 * kPointerSize)); 13553 __ mov(esi, Operand(esp, 3 * kPointerSize));
13548 __ add(Operand(esi), 13554 __ add(Operand(esi),
13549 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 13555 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
13550 __ mov(ebx, Operand(esp, 2 * kPointerSize)); // from 13556 __ mov(ebx, Operand(esp, 2 * kPointerSize)); // from
13551 // As from is a smi it is 2 times the value which matches the size of a two 13557 // As from is a smi it is 2 times the value which matches the size of a two
13552 // byte character. 13558 // byte character.
13553 ASSERT_EQ(0, kSmiTag); 13559 STATIC_ASSERT(kSmiTag == 0);
13554 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 13560 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
13555 __ add(esi, Operand(ebx)); 13561 __ add(esi, Operand(ebx));
13556 13562
13557 // eax: result string 13563 // eax: result string
13558 // ecx: result length 13564 // ecx: result length
13559 // edx: original value of esi 13565 // edx: original value of esi
13560 // edi: first character of result 13566 // edi: first character of result
13561 // esi: character of sub string start 13567 // esi: character of sub string start
13562 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false); 13568 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false);
13563 __ mov(esi, edx); // Restore esi. 13569 __ mov(esi, edx); // Restore esi.
13564 13570
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
13630 __ add(Operand(index), Immediate(1)); 13636 __ add(Operand(index), Immediate(1));
13631 __ j(not_zero, &loop); 13637 __ j(not_zero, &loop);
13632 } 13638 }
13633 13639
13634 // Compare lengths - strings up to min-length are equal. 13640 // Compare lengths - strings up to min-length are equal.
13635 __ bind(&compare_lengths); 13641 __ bind(&compare_lengths);
13636 __ test(length_delta, Operand(length_delta)); 13642 __ test(length_delta, Operand(length_delta));
13637 __ j(not_zero, &result_not_equal); 13643 __ j(not_zero, &result_not_equal);
13638 13644
13639 // Result is EQUAL. 13645 // Result is EQUAL.
13640 ASSERT_EQ(0, EQUAL); 13646 STATIC_ASSERT(EQUAL == 0);
13641 ASSERT_EQ(0, kSmiTag); 13647 STATIC_ASSERT(kSmiTag == 0);
13642 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 13648 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
13643 __ ret(0); 13649 __ ret(0);
13644 13650
13645 __ bind(&result_not_equal); 13651 __ bind(&result_not_equal);
13646 __ j(greater, &result_greater); 13652 __ j(greater, &result_greater);
13647 13653
13648 // Result is LESS. 13654 // Result is LESS.
13649 __ Set(eax, Immediate(Smi::FromInt(LESS))); 13655 __ Set(eax, Immediate(Smi::FromInt(LESS)));
13650 __ ret(0); 13656 __ ret(0);
13651 13657
(...skipping 11 matching lines...) Expand all
13663 // esp[0]: return address 13669 // esp[0]: return address
13664 // esp[4]: right string 13670 // esp[4]: right string
13665 // esp[8]: left string 13671 // esp[8]: left string
13666 13672
13667 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left 13673 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left
13668 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right 13674 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right
13669 13675
13670 Label not_same; 13676 Label not_same;
13671 __ cmp(edx, Operand(eax)); 13677 __ cmp(edx, Operand(eax));
13672 __ j(not_equal, &not_same); 13678 __ j(not_equal, &not_same);
13673 ASSERT_EQ(0, EQUAL); 13679 STATIC_ASSERT(EQUAL == 0);
13674 ASSERT_EQ(0, kSmiTag); 13680 STATIC_ASSERT(kSmiTag == 0);
13675 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 13681 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
13676 __ IncrementCounter(&Counters::string_compare_native, 1); 13682 __ IncrementCounter(&Counters::string_compare_native, 1);
13677 __ ret(2 * kPointerSize); 13683 __ ret(2 * kPointerSize);
13678 13684
13679 __ bind(&not_same); 13685 __ bind(&not_same);
13680 13686
13681 // Check that both objects are sequential ascii strings. 13687 // Check that both objects are sequential ascii strings.
13682 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); 13688 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
13683 13689
13684 // Compare flat ascii strings. 13690 // Compare flat ascii strings.
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
13897 masm.GetCode(&desc); 13903 masm.GetCode(&desc);
13898 // Call the function from C++. 13904 // Call the function from C++.
13899 return FUNCTION_CAST<MemCopyFunction>(buffer); 13905 return FUNCTION_CAST<MemCopyFunction>(buffer);
13900 } 13906 }
13901 13907
13902 #undef __ 13908 #undef __
13903 13909
13904 } } // namespace v8::internal 13910 } } // namespace v8::internal
13905 13911
13906 #endif // V8_TARGET_ARCH_IA32 13912 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.cc ('k') | src/x64/codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698