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

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

Issue 2586001: Add test_b(Operand, immediate) to ia32 assembler, and use it where possible. ... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 2606 matching lines...) Expand 10 before | Expand all | Expand 10 after
2617 dest->true_target()->Branch(equal); 2617 dest->true_target()->Branch(equal);
2618 __ test(operand.reg(), Immediate(kSmiTagMask)); 2618 __ test(operand.reg(), Immediate(kSmiTagMask));
2619 dest->false_target()->Branch(equal); 2619 dest->false_target()->Branch(equal);
2620 2620
2621 // It can be an undetectable object. 2621 // It can be an undetectable object.
2622 // Use a scratch register in preference to spilling operand.reg(). 2622 // Use a scratch register in preference to spilling operand.reg().
2623 Result temp = allocator()->Allocate(); 2623 Result temp = allocator()->Allocate();
2624 ASSERT(temp.is_valid()); 2624 ASSERT(temp.is_valid());
2625 __ mov(temp.reg(), 2625 __ mov(temp.reg(),
2626 FieldOperand(operand.reg(), HeapObject::kMapOffset)); 2626 FieldOperand(operand.reg(), HeapObject::kMapOffset));
2627 __ movzx_b(temp.reg(), 2627 __ test_b(FieldOperand(temp.reg(), Map::kBitFieldOffset),
2628 FieldOperand(temp.reg(), Map::kBitFieldOffset)); 2628 1 << Map::kIsUndetectable);
2629 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
2630 temp.Unuse(); 2629 temp.Unuse();
2631 operand.Unuse(); 2630 operand.Unuse();
2632 dest->Split(not_zero); 2631 dest->Split(not_zero);
2633 } 2632 }
2634 } else if (left_side_constant_1_char_string || 2633 } else if (left_side_constant_1_char_string ||
2635 right_side_constant_1_char_string) { 2634 right_side_constant_1_char_string) {
2636 if (left_side_constant_1_char_string && right_side_constant_1_char_string) { 2635 if (left_side_constant_1_char_string && right_side_constant_1_char_string) {
2637 // Trivial case, comparing two constants. 2636 // Trivial case, comparing two constants.
2638 int left_value = String::cast(*left_side.handle())->Get(0); 2637 int left_value = String::cast(*left_side.handle())->Get(0);
2639 int right_value = String::cast(*right_side.handle())->Get(0); 2638 int right_value = String::cast(*right_side.handle())->Get(0);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2713 result.ToRegister(); 2712 result.ToRegister();
2714 __ cmp(result.reg(), 0); 2713 __ cmp(result.reg(), 0);
2715 result.Unuse(); 2714 result.Unuse();
2716 dest->true_target()->Branch(cc); 2715 dest->true_target()->Branch(cc);
2717 dest->false_target()->Jump(); 2716 dest->false_target()->Jump();
2718 2717
2719 is_string.Bind(&left_side); 2718 is_string.Bind(&left_side);
2720 // left_side is a sequential ASCII string. 2719 // left_side is a sequential ASCII string.
2721 left_side = Result(left_reg); 2720 left_side = Result(left_reg);
2722 right_side = Result(right_val); 2721 right_side = Result(right_val);
2723 Result temp2 = allocator_->Allocate();
2724 ASSERT(temp2.is_valid());
2725 // Test string equality and comparison. 2722 // Test string equality and comparison.
2723 Label comparison_done;
2726 if (cc == equal) { 2724 if (cc == equal) {
2727 Label comparison_done;
2728 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2725 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2729 Immediate(Smi::FromInt(1))); 2726 Immediate(Smi::FromInt(1)));
2730 __ j(not_equal, &comparison_done); 2727 __ j(not_equal, &comparison_done);
2731 uint8_t char_value = 2728 uint8_t char_value =
2732 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 2729 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2733 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize), 2730 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
2734 char_value); 2731 char_value);
2735 __ bind(&comparison_done);
2736 } else { 2732 } else {
2737 __ mov(temp2.reg(), 2733 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2738 FieldOperand(left_side.reg(), String::kLengthOffset)); 2734 Immediate(Smi::FromInt(1)));
2739 __ SmiUntag(temp2.reg()); 2735 // If the length is 0 then the jump is taken and the flags
2740 __ sub(Operand(temp2.reg()), Immediate(1)); 2736 // correctly represent being less than the one-character string.
2741 Label comparison; 2737 __ j(below, &comparison_done);
2742 // If the length is 0 then the subtraction gave -1 which compares less
2743 // than any character.
2744 __ j(negative, &comparison);
2745 // Otherwise load the first character.
2746 __ movzx_b(temp2.reg(),
2747 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
2748 __ bind(&comparison);
2749 // Compare the first character of the string with the 2738 // Compare the first character of the string with the
2750 // constant 1-character string. 2739 // constant 1-character string.
2751 uint8_t char_value = 2740 uint8_t char_value =
2752 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 2741 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
2753 __ cmp(Operand(temp2.reg()), Immediate(char_value)); 2742 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
2754 Label characters_were_different; 2743 char_value);
2755 __ j(not_equal, &characters_were_different); 2744 __ j(not_equal, &comparison_done);
2756 // If the first character is the same then the long string sorts after 2745 // If the first character is the same then the long string sorts after
2757 // the short one. 2746 // the short one.
2758 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2747 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2759 Immediate(Smi::FromInt(1))); 2748 Immediate(Smi::FromInt(1)));
2760 __ bind(&characters_were_different);
2761 } 2749 }
2762 temp2.Unuse(); 2750 __ bind(&comparison_done);
2763 left_side.Unuse(); 2751 left_side.Unuse();
2764 right_side.Unuse(); 2752 right_side.Unuse();
2765 dest->Split(cc); 2753 dest->Split(cc);
2766 } 2754 }
2767 } else { 2755 } else {
2768 // Neither side is a constant Smi, constant 1-char string or constant null. 2756 // Neither side is a constant Smi, constant 1-char string or constant null.
2769 // If either side is a non-smi constant, or known to be a heap number skip 2757 // If either side is a non-smi constant, or known to be a heap number skip
2770 // the smi check. 2758 // the smi check.
2771 bool known_non_smi = 2759 bool known_non_smi =
2772 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 2760 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
(...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after
4141 // [iteration counter (smi)] <- slot 0 4129 // [iteration counter (smi)] <- slot 0
4142 // [length of array] <- slot 1 4130 // [length of array] <- slot 1
4143 // [FixedArray] <- slot 2 4131 // [FixedArray] <- slot 2
4144 // [Map or 0] <- slot 3 4132 // [Map or 0] <- slot 3
4145 // [Object] <- slot 4 4133 // [Object] <- slot 4
4146 4134
4147 // Check if enumerable is already a JSObject 4135 // Check if enumerable is already a JSObject
4148 // eax: value to be iterated over 4136 // eax: value to be iterated over
4149 __ test(eax, Immediate(kSmiTagMask)); 4137 __ test(eax, Immediate(kSmiTagMask));
4150 primitive.Branch(zero); 4138 primitive.Branch(zero);
4151 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 4139 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
4152 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
4153 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
4154 jsobject.Branch(above_equal); 4140 jsobject.Branch(above_equal);
4155 4141
4156 primitive.Bind(); 4142 primitive.Bind();
4157 frame_->EmitPush(eax); 4143 frame_->EmitPush(eax);
4158 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1); 4144 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
4159 // function call returns the value in eax, which is where we want it below 4145 // function call returns the value in eax, which is where we want it below
4160 4146
4161 jsobject.Bind(); 4147 jsobject.Bind();
4162 // Get the set of properties (as a FixedArray or Map). 4148 // Get the set of properties (as a FixedArray or Map).
4163 // eax: value to be iterated over 4149 // eax: value to be iterated over
(...skipping 2146 matching lines...) Expand 10 before | Expand all | Expand 10 after
6310 6296
6311 __ test(obj.reg(), Immediate(kSmiTagMask)); 6297 __ test(obj.reg(), Immediate(kSmiTagMask));
6312 destination()->false_target()->Branch(zero); 6298 destination()->false_target()->Branch(zero);
6313 __ cmp(obj.reg(), Factory::null_value()); 6299 __ cmp(obj.reg(), Factory::null_value());
6314 destination()->true_target()->Branch(equal); 6300 destination()->true_target()->Branch(equal);
6315 6301
6316 Result map = allocator()->Allocate(); 6302 Result map = allocator()->Allocate();
6317 ASSERT(map.is_valid()); 6303 ASSERT(map.is_valid());
6318 __ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset)); 6304 __ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
6319 // Undetectable objects behave like undefined when tested with typeof. 6305 // Undetectable objects behave like undefined when tested with typeof.
6320 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kBitFieldOffset)); 6306 __ test_b(FieldOperand(map.reg(), Map::kBitFieldOffset),
6321 __ test(map.reg(), Immediate(1 << Map::kIsUndetectable)); 6307 1 << Map::kIsUndetectable);
6322 destination()->false_target()->Branch(not_zero); 6308 destination()->false_target()->Branch(not_zero);
6323 __ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset)); 6309 // Do a range test for JSObject type. We can't use
6310 // MacroAssembler::IsInstanceJSObjectType, because we are using a
6311 // ControlDestination, so we copy its implementation here.
6324 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset)); 6312 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
6325 __ cmp(map.reg(), FIRST_JS_OBJECT_TYPE); 6313 __ sub(Operand(map.reg()), Immediate(FIRST_JS_OBJECT_TYPE));
6326 destination()->false_target()->Branch(below); 6314 __ cmp(map.reg(), LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE);
6327 __ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
6328 obj.Unuse(); 6315 obj.Unuse();
6329 map.Unuse(); 6316 map.Unuse();
6330 destination()->Split(below_equal); 6317 destination()->Split(below_equal);
6331 } 6318 }
6332 6319
6333 6320
6334 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { 6321 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
6335 // This generates a fast version of: 6322 // This generates a fast version of:
6336 // (%_ClassOf(arg) === 'Function') 6323 // (%_ClassOf(arg) === 'Function')
6337 ASSERT(args->length() == 1); 6324 ASSERT(args->length() == 1);
(...skipping 15 matching lines...) Expand all
6353 ASSERT(args->length() == 1); 6340 ASSERT(args->length() == 1);
6354 Load(args->at(0)); 6341 Load(args->at(0));
6355 Result obj = frame_->Pop(); 6342 Result obj = frame_->Pop();
6356 obj.ToRegister(); 6343 obj.ToRegister();
6357 __ test(obj.reg(), Immediate(kSmiTagMask)); 6344 __ test(obj.reg(), Immediate(kSmiTagMask));
6358 destination()->false_target()->Branch(zero); 6345 destination()->false_target()->Branch(zero);
6359 Result temp = allocator()->Allocate(); 6346 Result temp = allocator()->Allocate();
6360 ASSERT(temp.is_valid()); 6347 ASSERT(temp.is_valid());
6361 __ mov(temp.reg(), 6348 __ mov(temp.reg(),
6362 FieldOperand(obj.reg(), HeapObject::kMapOffset)); 6349 FieldOperand(obj.reg(), HeapObject::kMapOffset));
6363 __ movzx_b(temp.reg(), 6350 __ test_b(FieldOperand(temp.reg(), Map::kBitFieldOffset),
6364 FieldOperand(temp.reg(), Map::kBitFieldOffset)); 6351 1 << Map::kIsUndetectable);
6365 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
6366 obj.Unuse(); 6352 obj.Unuse();
6367 temp.Unuse(); 6353 temp.Unuse();
6368 destination()->Split(not_zero); 6354 destination()->Split(not_zero);
6369 } 6355 }
6370 6356
6371 6357
6372 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { 6358 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
6373 ASSERT(args->length() == 0); 6359 ASSERT(args->length() == 0);
6374 6360
6375 // Get the frame pointer for the calling frame. 6361 // Get the frame pointer for the calling frame.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
6429 Result obj = frame_->Pop(); 6415 Result obj = frame_->Pop();
6430 obj.ToRegister(); 6416 obj.ToRegister();
6431 frame_->Spill(obj.reg()); 6417 frame_->Spill(obj.reg());
6432 6418
6433 // If the object is a smi, we return null. 6419 // If the object is a smi, we return null.
6434 __ test(obj.reg(), Immediate(kSmiTagMask)); 6420 __ test(obj.reg(), Immediate(kSmiTagMask));
6435 null.Branch(zero); 6421 null.Branch(zero);
6436 6422
6437 // Check that the object is a JS object but take special care of JS 6423 // Check that the object is a JS object but take special care of JS
6438 // functions to make sure they have 'Function' as their class. 6424 // functions to make sure they have 'Function' as their class.
6439 { Result tmp = allocator()->Allocate(); 6425 __ CmpObjectType(obj.reg(), FIRST_JS_OBJECT_TYPE, obj.reg());
6440 __ mov(obj.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset)); 6426 null.Branch(below);
6441 __ movzx_b(tmp.reg(), FieldOperand(obj.reg(), Map::kInstanceTypeOffset));
6442 __ cmp(tmp.reg(), FIRST_JS_OBJECT_TYPE);
6443 null.Branch(below);
6444 6427
6445 // As long as JS_FUNCTION_TYPE is the last instance type and it is 6428 // As long as JS_FUNCTION_TYPE is the last instance type and it is
6446 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 6429 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
6447 // LAST_JS_OBJECT_TYPE. 6430 // LAST_JS_OBJECT_TYPE.
6448 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 6431 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
6449 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 6432 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
6450 __ cmp(tmp.reg(), JS_FUNCTION_TYPE); 6433 __ CmpInstanceType(obj.reg(), JS_FUNCTION_TYPE);
6451 function.Branch(equal); 6434 function.Branch(equal);
6452 }
6453 6435
6454 // Check if the constructor in the map is a function. 6436 // Check if the constructor in the map is a function.
6455 { Result tmp = allocator()->Allocate(); 6437 { Result tmp = allocator()->Allocate();
6456 __ mov(obj.reg(), FieldOperand(obj.reg(), Map::kConstructorOffset)); 6438 __ mov(obj.reg(), FieldOperand(obj.reg(), Map::kConstructorOffset));
6457 __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, tmp.reg()); 6439 __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, tmp.reg());
6458 non_function_constructor.Branch(not_equal); 6440 non_function_constructor.Branch(not_equal);
6459 } 6441 }
6460 6442
6461 // The map register now contains the constructor function. Grab the 6443 // The map register now contains the constructor function. Grab the
6462 // instance class name from there. 6444 // instance class name from there.
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after
7023 7005
7024 DeferredSwapElements* deferred = new DeferredSwapElements(object.reg(), 7006 DeferredSwapElements* deferred = new DeferredSwapElements(object.reg(),
7025 index1.reg(), 7007 index1.reg(),
7026 index2.reg()); 7008 index2.reg());
7027 7009
7028 // Fetch the map and check if array is in fast case. 7010 // Fetch the map and check if array is in fast case.
7029 // Check that object doesn't require security checks and 7011 // Check that object doesn't require security checks and
7030 // has no indexed interceptor. 7012 // has no indexed interceptor.
7031 __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg()); 7013 __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg());
7032 deferred->Branch(below); 7014 deferred->Branch(below);
7033 __ movzx_b(tmp1.reg(), FieldOperand(tmp1.reg(), Map::kBitFieldOffset)); 7015 __ test_b(FieldOperand(tmp1.reg(), Map::kBitFieldOffset),
7034 __ test(tmp1.reg(), Immediate(KeyedLoadIC::kSlowCaseBitFieldMask)); 7016 KeyedLoadIC::kSlowCaseBitFieldMask);
7035 deferred->Branch(not_zero); 7017 deferred->Branch(not_zero);
7036 7018
7037 // Check the object's elements are in fast case. 7019 // Check the object's elements are in fast case.
7038 __ mov(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset)); 7020 __ mov(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset));
7039 __ cmp(FieldOperand(tmp1.reg(), HeapObject::kMapOffset), 7021 __ cmp(FieldOperand(tmp1.reg(), HeapObject::kMapOffset),
7040 Immediate(Factory::fixed_array_map())); 7022 Immediate(Factory::fixed_array_map()));
7041 deferred->Branch(not_equal); 7023 deferred->Branch(not_equal);
7042 7024
7043 // Smi-tagging is equivalent to multiplying by 2. 7025 // Smi-tagging is equivalent to multiplying by 2.
7044 STATIC_ASSERT(kSmiTag == 0); 7026 STATIC_ASSERT(kSmiTag == 0);
(...skipping 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after
8278 destination()->Split(equal); 8260 destination()->Split(equal);
8279 8261
8280 } else if (check->Equals(Heap::string_symbol())) { 8262 } else if (check->Equals(Heap::string_symbol())) {
8281 __ test(answer.reg(), Immediate(kSmiTagMask)); 8263 __ test(answer.reg(), Immediate(kSmiTagMask));
8282 destination()->false_target()->Branch(zero); 8264 destination()->false_target()->Branch(zero);
8283 8265
8284 // It can be an undetectable string object. 8266 // It can be an undetectable string object.
8285 Result temp = allocator()->Allocate(); 8267 Result temp = allocator()->Allocate();
8286 ASSERT(temp.is_valid()); 8268 ASSERT(temp.is_valid());
8287 __ mov(temp.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset)); 8269 __ mov(temp.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
8288 __ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kBitFieldOffset)); 8270 __ test_b(FieldOperand(temp.reg(), Map::kBitFieldOffset),
8289 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable)); 8271 1 << Map::kIsUndetectable);
8290 destination()->false_target()->Branch(not_zero); 8272 destination()->false_target()->Branch(not_zero);
8291 __ CmpObjectType(answer.reg(), FIRST_NONSTRING_TYPE, temp.reg()); 8273 __ CmpInstanceType(temp.reg(), FIRST_NONSTRING_TYPE);
8292 temp.Unuse(); 8274 temp.Unuse();
8293 answer.Unuse(); 8275 answer.Unuse();
8294 destination()->Split(below); 8276 destination()->Split(below);
8295 8277
8296 } else if (check->Equals(Heap::boolean_symbol())) { 8278 } else if (check->Equals(Heap::boolean_symbol())) {
8297 __ cmp(answer.reg(), Factory::true_value()); 8279 __ cmp(answer.reg(), Factory::true_value());
8298 destination()->true_target()->Branch(equal); 8280 destination()->true_target()->Branch(equal);
8299 __ cmp(answer.reg(), Factory::false_value()); 8281 __ cmp(answer.reg(), Factory::false_value());
8300 answer.Unuse(); 8282 answer.Unuse();
8301 destination()->Split(equal); 8283 destination()->Split(equal);
8302 8284
8303 } else if (check->Equals(Heap::undefined_symbol())) { 8285 } else if (check->Equals(Heap::undefined_symbol())) {
8304 __ cmp(answer.reg(), Factory::undefined_value()); 8286 __ cmp(answer.reg(), Factory::undefined_value());
8305 destination()->true_target()->Branch(equal); 8287 destination()->true_target()->Branch(equal);
8306 8288
8307 __ test(answer.reg(), Immediate(kSmiTagMask)); 8289 __ test(answer.reg(), Immediate(kSmiTagMask));
8308 destination()->false_target()->Branch(zero); 8290 destination()->false_target()->Branch(zero);
8309 8291
8310 // It can be an undetectable object. 8292 // It can be an undetectable object.
8311 frame_->Spill(answer.reg()); 8293 frame_->Spill(answer.reg());
8312 __ mov(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset)); 8294 __ mov(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
8313 __ movzx_b(answer.reg(), 8295 __ test_b(FieldOperand(answer.reg(), Map::kBitFieldOffset),
8314 FieldOperand(answer.reg(), Map::kBitFieldOffset)); 8296 1 << Map::kIsUndetectable);
8315 __ test(answer.reg(), Immediate(1 << Map::kIsUndetectable));
8316 answer.Unuse(); 8297 answer.Unuse();
8317 destination()->Split(not_zero); 8298 destination()->Split(not_zero);
8318 8299
8319 } else if (check->Equals(Heap::function_symbol())) { 8300 } else if (check->Equals(Heap::function_symbol())) {
8320 __ test(answer.reg(), Immediate(kSmiTagMask)); 8301 __ test(answer.reg(), Immediate(kSmiTagMask));
8321 destination()->false_target()->Branch(zero); 8302 destination()->false_target()->Branch(zero);
8322 frame_->Spill(answer.reg()); 8303 frame_->Spill(answer.reg());
8323 __ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg()); 8304 __ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg());
8324 destination()->true_target()->Branch(equal); 8305 destination()->true_target()->Branch(equal);
8325 // Regular expressions are callable so typeof == 'function'. 8306 // Regular expressions are callable so typeof == 'function'.
8326 __ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE); 8307 __ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE);
8327 answer.Unuse(); 8308 answer.Unuse();
8328 destination()->Split(equal); 8309 destination()->Split(equal);
8329 } else if (check->Equals(Heap::object_symbol())) { 8310 } else if (check->Equals(Heap::object_symbol())) {
8330 __ test(answer.reg(), Immediate(kSmiTagMask)); 8311 __ test(answer.reg(), Immediate(kSmiTagMask));
8331 destination()->false_target()->Branch(zero); 8312 destination()->false_target()->Branch(zero);
8332 __ cmp(answer.reg(), Factory::null_value()); 8313 __ cmp(answer.reg(), Factory::null_value());
8333 destination()->true_target()->Branch(equal); 8314 destination()->true_target()->Branch(equal);
8334 8315
8335 Result map = allocator()->Allocate(); 8316 Result map = allocator()->Allocate();
8336 ASSERT(map.is_valid()); 8317 ASSERT(map.is_valid());
8337 // Regular expressions are typeof == 'function', not 'object'. 8318 // Regular expressions are typeof == 'function', not 'object'.
8338 __ CmpObjectType(answer.reg(), JS_REGEXP_TYPE, map.reg()); 8319 __ CmpObjectType(answer.reg(), JS_REGEXP_TYPE, map.reg());
8339 destination()->false_target()->Branch(equal); 8320 destination()->false_target()->Branch(equal);
8340 8321
8341 // It can be an undetectable object. 8322 // It can be an undetectable object.
8342 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kBitFieldOffset)); 8323 __ test_b(FieldOperand(map.reg(), Map::kBitFieldOffset),
8343 __ test(map.reg(), Immediate(1 << Map::kIsUndetectable)); 8324 1 << Map::kIsUndetectable);
8344 destination()->false_target()->Branch(not_zero); 8325 destination()->false_target()->Branch(not_zero);
8345 __ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset)); 8326 // Do a range test for JSObject type. We can't use
8327 // MacroAssembler::IsInstanceJSObjectType, because we are using a
8328 // ControlDestination, so we copy its implementation here.
8346 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset)); 8329 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
8347 __ cmp(map.reg(), FIRST_JS_OBJECT_TYPE); 8330 __ sub(Operand(map.reg()), Immediate(FIRST_JS_OBJECT_TYPE));
8348 destination()->false_target()->Branch(below); 8331 __ cmp(map.reg(), LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE);
8349 __ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
8350 answer.Unuse(); 8332 answer.Unuse();
8351 map.Unuse(); 8333 map.Unuse();
8352 destination()->Split(below_equal); 8334 destination()->Split(below_equal);
8353 } else { 8335 } else {
8354 // Uncommon case: typeof testing against a string literal that is 8336 // Uncommon case: typeof testing against a string literal that is
8355 // never returned from the typeof operator. 8337 // never returned from the typeof operator.
8356 answer.Unuse(); 8338 answer.Unuse();
8357 destination()->Goto(false); 8339 destination()->Goto(false);
8358 } 8340 }
8359 return; 8341 return;
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after
9266 9248
9267 // 'null' => false. 9249 // 'null' => false.
9268 __ cmp(eax, Factory::null_value()); 9250 __ cmp(eax, Factory::null_value());
9269 __ j(equal, &false_result); 9251 __ j(equal, &false_result);
9270 9252
9271 // Get the map and type of the heap object. 9253 // Get the map and type of the heap object.
9272 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 9254 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
9273 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); 9255 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
9274 9256
9275 // Undetectable => false. 9257 // Undetectable => false.
9276 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset)); 9258 __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
9277 __ and_(ebx, 1 << Map::kIsUndetectable); 9259 1 << Map::kIsUndetectable);
9278 __ j(not_zero, &false_result); 9260 __ j(not_zero, &false_result);
9279 9261
9280 // JavaScript object => true. 9262 // JavaScript object => true.
9281 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 9263 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE);
9282 __ j(above_equal, &true_result); 9264 __ j(above_equal, &true_result);
9283 9265
9284 // String value => false iff empty. 9266 // String value => false iff empty.
9285 __ cmp(ecx, FIRST_NONSTRING_TYPE); 9267 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
9286 __ j(above_equal, &not_string); 9268 __ j(above_equal, &not_string);
9287 __ mov(edx, FieldOperand(eax, String::kLengthOffset));
9288 ASSERT(kSmiTag == 0); 9269 ASSERT(kSmiTag == 0);
9289 __ test(edx, Operand(edx)); 9270 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0));
9290 __ j(zero, &false_result); 9271 __ j(zero, &false_result);
9291 __ jmp(&true_result); 9272 __ jmp(&true_result);
9292 9273
9293 __ bind(&not_string); 9274 __ bind(&not_string);
9294 // HeapNumber => false iff +0, -0, or NaN. 9275 // HeapNumber => false iff +0, -0, or NaN.
9295 __ cmp(edx, Factory::heap_number_map()); 9276 __ cmp(edx, Factory::heap_number_map());
9296 __ j(not_equal, &true_result); 9277 __ j(not_equal, &true_result);
9297 __ fldz(); 9278 __ fldz();
9298 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 9279 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
9299 __ FCmp(); 9280 __ FCmp();
(...skipping 2435 matching lines...) Expand 10 before | Expand all | Expand 10 after
11735 __ ret(0); 11716 __ ret(0);
11736 11717
11737 __ bind(&not_smis); 11718 __ bind(&not_smis);
11738 } 11719 }
11739 11720
11740 // If either operand is a JSObject or an oddball value, then they are not 11721 // If either operand is a JSObject or an oddball value, then they are not
11741 // equal since their pointers are different 11722 // equal since their pointers are different
11742 // There is no test for undetectability in strict equality. 11723 // There is no test for undetectability in strict equality.
11743 11724
11744 // Get the type of the first operand. 11725 // Get the type of the first operand.
11745 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
11746 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
11747
11748 // If the first object is a JS object, we have done pointer comparison. 11726 // If the first object is a JS object, we have done pointer comparison.
11727 Label first_non_object;
11749 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 11728 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
11750 Label first_non_object; 11729 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
11751 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
11752 __ j(below, &first_non_object); 11730 __ j(below, &first_non_object);
11753 11731
11754 // Return non-zero (eax is not zero) 11732 // Return non-zero (eax is not zero)
11755 Label return_not_equal; 11733 Label return_not_equal;
11756 ASSERT(kHeapObjectTag != 0); 11734 ASSERT(kHeapObjectTag != 0);
11757 __ bind(&return_not_equal); 11735 __ bind(&return_not_equal);
11758 __ ret(0); 11736 __ ret(0);
11759 11737
11760 __ bind(&first_non_object); 11738 __ bind(&first_non_object);
11761 // Check for oddballs: true, false, null, undefined. 11739 // Check for oddballs: true, false, null, undefined.
11762 __ cmp(ecx, ODDBALL_TYPE); 11740 __ CmpInstanceType(ecx, ODDBALL_TYPE);
11763 __ j(equal, &return_not_equal); 11741 __ j(equal, &return_not_equal);
11764 11742
11765 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 11743 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx);
11766 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
11767
11768 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
11769 __ j(above_equal, &return_not_equal); 11744 __ j(above_equal, &return_not_equal);
11770 11745
11771 // Check for oddballs: true, false, null, undefined. 11746 // Check for oddballs: true, false, null, undefined.
11772 __ cmp(ecx, ODDBALL_TYPE); 11747 __ CmpInstanceType(ecx, ODDBALL_TYPE);
11773 __ j(equal, &return_not_equal); 11748 __ j(equal, &return_not_equal);
11774 11749
11775 // Fall through to the general case. 11750 // Fall through to the general case.
11776 } 11751 }
11777 __ bind(&slow); 11752 __ bind(&slow);
11778 } 11753 }
11779 11754
11780 // Push arguments below the return address. 11755 // Push arguments below the return address.
11781 __ pop(ecx); 11756 __ pop(ecx);
11782 __ push(eax); 11757 __ push(eax);
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after
12404 12379
12405 12380
12406 void InstanceofStub::Generate(MacroAssembler* masm) { 12381 void InstanceofStub::Generate(MacroAssembler* masm) {
12407 // Get the object - go slow case if it's a smi. 12382 // Get the object - go slow case if it's a smi.
12408 Label slow; 12383 Label slow;
12409 __ mov(eax, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, function 12384 __ mov(eax, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, function
12410 __ test(eax, Immediate(kSmiTagMask)); 12385 __ test(eax, Immediate(kSmiTagMask));
12411 __ j(zero, &slow, not_taken); 12386 __ j(zero, &slow, not_taken);
12412 12387
12413 // Check that the left hand is a JS object. 12388 // Check that the left hand is a JS object.
12414 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); // eax - object map 12389 __ IsObjectJSObjectType(eax, eax, edx, &slow);
12415 __ movzx_b(ecx, FieldOperand(eax, Map::kInstanceTypeOffset)); // ecx - type
12416 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
12417 __ j(below, &slow, not_taken);
12418 __ cmp(ecx, LAST_JS_OBJECT_TYPE);
12419 __ j(above, &slow, not_taken);
12420 12390
12421 // Get the prototype of the function. 12391 // Get the prototype of the function.
12422 __ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address 12392 __ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address
12423 // edx is function, eax is map. 12393 // edx is function, eax is map.
12424 12394
12425 // Look up the function and the map in the instanceof cache. 12395 // Look up the function and the map in the instanceof cache.
12426 Label miss; 12396 Label miss;
12427 ExternalReference roots_address = ExternalReference::roots_address(); 12397 ExternalReference roots_address = ExternalReference::roots_address();
12428 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); 12398 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
12429 __ cmp(edx, Operand::StaticArray(ecx, times_pointer_size, roots_address)); 12399 __ cmp(edx, Operand::StaticArray(ecx, times_pointer_size, roots_address));
12430 __ j(not_equal, &miss); 12400 __ j(not_equal, &miss);
12431 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex)); 12401 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex));
12432 __ cmp(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address)); 12402 __ cmp(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address));
12433 __ j(not_equal, &miss); 12403 __ j(not_equal, &miss);
12434 __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); 12404 __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
12435 __ mov(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address)); 12405 __ mov(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address));
12436 __ ret(2 * kPointerSize); 12406 __ ret(2 * kPointerSize);
12437 12407
12438 __ bind(&miss); 12408 __ bind(&miss);
12439 __ TryGetFunctionPrototype(edx, ebx, ecx, &slow); 12409 __ TryGetFunctionPrototype(edx, ebx, ecx, &slow);
12440 12410
12441 // Check that the function prototype is a JS object. 12411 // Check that the function prototype is a JS object.
12442 __ test(ebx, Immediate(kSmiTagMask)); 12412 __ test(ebx, Immediate(kSmiTagMask));
12443 __ j(zero, &slow, not_taken); 12413 __ j(zero, &slow, not_taken);
12444 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); 12414 __ IsObjectJSObjectType(ebx, ecx, ecx, &slow);
12445 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12446 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
12447 __ j(below, &slow, not_taken);
12448 __ cmp(ecx, LAST_JS_OBJECT_TYPE);
12449 __ j(above, &slow, not_taken);
12450 12415
12451 // Register mapping: 12416 // Register mapping:
12452 // eax is object map. 12417 // eax is object map.
12453 // edx is function. 12418 // edx is function.
12454 // ebx is function prototype. 12419 // ebx is function prototype.
12455 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex)); 12420 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex));
12456 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax); 12421 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax);
12457 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); 12422 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
12458 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), edx); 12423 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), edx);
12459 12424
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
12874 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12839 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12875 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12840 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12876 __ and_(ecx, kStringRepresentationMask); 12841 __ and_(ecx, kStringRepresentationMask);
12877 __ cmp(ecx, kExternalStringTag); 12842 __ cmp(ecx, kExternalStringTag);
12878 __ j(equal, &string_add_runtime); 12843 __ j(equal, &string_add_runtime);
12879 // Now check if both strings are ascii strings. 12844 // Now check if both strings are ascii strings.
12880 // eax: first string 12845 // eax: first string
12881 // ebx: length of resulting flat string as a smi 12846 // ebx: length of resulting flat string as a smi
12882 // edx: second string 12847 // edx: second string
12883 Label non_ascii_string_add_flat_result; 12848 Label non_ascii_string_add_flat_result;
12849 ASSERT(kStringEncodingMask == kAsciiStringTag);
12884 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 12850 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
12885 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12851 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
12886 ASSERT(kStringEncodingMask == kAsciiStringTag);
12887 __ test(ecx, Immediate(kAsciiStringTag));
12888 __ j(zero, &non_ascii_string_add_flat_result); 12852 __ j(zero, &non_ascii_string_add_flat_result);
12889 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12853 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12890 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12854 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
12891 __ test(ecx, Immediate(kAsciiStringTag));
12892 __ j(zero, &string_add_runtime); 12855 __ j(zero, &string_add_runtime);
12893 12856
12894 __ bind(&make_flat_ascii_string); 12857 __ bind(&make_flat_ascii_string);
12895 // Both strings are ascii strings. As they are short they are both flat. 12858 // Both strings are ascii strings. As they are short they are both flat.
12896 // ebx: length of resulting flat string as a smi 12859 // ebx: length of resulting flat string as a smi
12897 __ SmiUntag(ebx); 12860 __ SmiUntag(ebx);
12898 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12861 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12899 // eax: result string 12862 // eax: result string
12900 __ mov(ecx, eax); 12863 __ mov(ecx, eax);
12901 // Locate first character of result. 12864 // Locate first character of result.
(...skipping 20 matching lines...) Expand all
12922 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12885 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12923 __ IncrementCounter(&Counters::string_add_native, 1); 12886 __ IncrementCounter(&Counters::string_add_native, 1);
12924 __ ret(2 * kPointerSize); 12887 __ ret(2 * kPointerSize);
12925 12888
12926 // Handle creating a flat two byte result. 12889 // Handle creating a flat two byte result.
12927 // eax: first string - known to be two byte 12890 // eax: first string - known to be two byte
12928 // ebx: length of resulting flat string as a smi 12891 // ebx: length of resulting flat string as a smi
12929 // edx: second string 12892 // edx: second string
12930 __ bind(&non_ascii_string_add_flat_result); 12893 __ bind(&non_ascii_string_add_flat_result);
12931 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12894 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12932 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12895 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
12933 __ and_(ecx, kAsciiStringTag);
12934 __ j(not_zero, &string_add_runtime); 12896 __ j(not_zero, &string_add_runtime);
12935 // Both strings are two byte strings. As they are short they are both 12897 // Both strings are two byte strings. As they are short they are both
12936 // flat. 12898 // flat.
12937 __ SmiUntag(ebx); 12899 __ SmiUntag(ebx);
12938 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12900 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12939 // eax: result string 12901 // eax: result string
12940 __ mov(ecx, eax); 12902 __ mov(ecx, eax);
12941 // Locate first character of result. 12903 // Locate first character of result.
12942 __ add(Operand(ecx), 12904 __ add(Operand(ecx),
12943 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12905 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
13492 // tagged as a small integer. 13454 // tagged as a small integer.
13493 __ bind(&runtime); 13455 __ bind(&runtime);
13494 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 13456 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
13495 } 13457 }
13496 13458
13497 #undef __ 13459 #undef __
13498 13460
13499 } } // namespace v8::internal 13461 } } // namespace v8::internal
13500 13462
13501 #endif // V8_TARGET_ARCH_IA32 13463 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698