| OLD | NEW | 
|---|
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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, ¬_string); | 9268   __ j(above_equal, ¬_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(¬_string); | 9274   __ bind(¬_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  Loading... | 
| 11735         __ ret(0); | 11716         __ ret(0); | 
| 11736 | 11717 | 
| 11737         __ bind(¬_smis); | 11718         __ bind(¬_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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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 | 
| OLD | NEW | 
|---|