| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 | 42 |
| 43 void ToNumberStub::Generate(MacroAssembler* masm) { | 43 void ToNumberStub::Generate(MacroAssembler* masm) { |
| 44 // The ToNumber stub takes one argument in eax. | 44 // The ToNumber stub takes one argument in eax. |
| 45 NearLabel check_heap_number, call_builtin; | 45 NearLabel check_heap_number, call_builtin; |
| 46 __ test(eax, Immediate(kSmiTagMask)); | 46 __ test(eax, Immediate(kSmiTagMask)); |
| 47 __ j(not_zero, &check_heap_number); | 47 __ j(not_zero, &check_heap_number); |
| 48 __ ret(0); | 48 __ ret(0); |
| 49 | 49 |
| 50 __ bind(&check_heap_number); | 50 __ bind(&check_heap_number); |
| 51 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 51 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 52 __ cmp(Operand(ebx), Immediate(FACTORY->heap_number_map())); | 52 Factory* factory = masm->isolate()->factory(); |
| 53 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); |
| 53 __ j(not_equal, &call_builtin); | 54 __ j(not_equal, &call_builtin); |
| 54 __ ret(0); | 55 __ ret(0); |
| 55 | 56 |
| 56 __ bind(&call_builtin); | 57 __ bind(&call_builtin); |
| 57 __ pop(ecx); // Pop return address. | 58 __ pop(ecx); // Pop return address. |
| 58 __ push(eax); | 59 __ push(eax); |
| 59 __ push(ecx); // Push return address. | 60 __ push(ecx); // Push return address. |
| 60 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); | 61 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); |
| 61 } | 62 } |
| 62 | 63 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 76 | 77 |
| 77 // Compute the function map in the current global context and set that | 78 // Compute the function map in the current global context and set that |
| 78 // as the map of the allocated object. | 79 // as the map of the allocated object. |
| 79 __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 80 __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 80 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); | 81 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); |
| 81 __ mov(ecx, Operand(ecx, Context::SlotOffset(map_index))); | 82 __ mov(ecx, Operand(ecx, Context::SlotOffset(map_index))); |
| 82 __ mov(FieldOperand(eax, JSObject::kMapOffset), ecx); | 83 __ mov(FieldOperand(eax, JSObject::kMapOffset), ecx); |
| 83 | 84 |
| 84 // Initialize the rest of the function. We don't have to update the | 85 // Initialize the rest of the function. We don't have to update the |
| 85 // write barrier because the allocated object is in new space. | 86 // write barrier because the allocated object is in new space. |
| 86 __ mov(ebx, Immediate(FACTORY->empty_fixed_array())); | 87 Factory* factory = masm->isolate()->factory(); |
| 88 __ mov(ebx, Immediate(factory->empty_fixed_array())); |
| 87 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ebx); | 89 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ebx); |
| 88 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); | 90 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); |
| 89 __ mov(FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset), | 91 __ mov(FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset), |
| 90 Immediate(FACTORY->the_hole_value())); | 92 Immediate(factory->the_hole_value())); |
| 91 __ mov(FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset), edx); | 93 __ mov(FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset), edx); |
| 92 __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi); | 94 __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi); |
| 93 __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx); | 95 __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx); |
| 94 __ mov(FieldOperand(eax, JSFunction::kNextFunctionLinkOffset), | 96 __ mov(FieldOperand(eax, JSFunction::kNextFunctionLinkOffset), |
| 95 Immediate(FACTORY->undefined_value())); | 97 Immediate(factory->undefined_value())); |
| 96 | 98 |
| 97 // Initialize the code pointer in the function to be the one | 99 // Initialize the code pointer in the function to be the one |
| 98 // found in the shared function info object. | 100 // found in the shared function info object. |
| 99 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); | 101 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); |
| 100 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); | 102 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); |
| 101 __ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx); | 103 __ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx); |
| 102 | 104 |
| 103 // Return and remove the on-stack parameter. | 105 // Return and remove the on-stack parameter. |
| 104 __ ret(1 * kPointerSize); | 106 __ ret(1 * kPointerSize); |
| 105 | 107 |
| 106 // Create a new closure through the slower runtime call. | 108 // Create a new closure through the slower runtime call. |
| 107 __ bind(&gc); | 109 __ bind(&gc); |
| 108 __ pop(ecx); // Temporarily remove return address. | 110 __ pop(ecx); // Temporarily remove return address. |
| 109 __ pop(edx); | 111 __ pop(edx); |
| 110 __ push(esi); | 112 __ push(esi); |
| 111 __ push(edx); | 113 __ push(edx); |
| 112 __ push(Immediate(FACTORY->false_value())); | 114 __ push(Immediate(factory->false_value())); |
| 113 __ push(ecx); // Restore return address. | 115 __ push(ecx); // Restore return address. |
| 114 __ TailCallRuntime(Runtime::kNewClosure, 3, 1); | 116 __ TailCallRuntime(Runtime::kNewClosure, 3, 1); |
| 115 } | 117 } |
| 116 | 118 |
| 117 | 119 |
| 118 void FastNewContextStub::Generate(MacroAssembler* masm) { | 120 void FastNewContextStub::Generate(MacroAssembler* masm) { |
| 119 // Try to allocate the context in new space. | 121 // Try to allocate the context in new space. |
| 120 Label gc; | 122 Label gc; |
| 121 int length = slots_ + Context::MIN_CONTEXT_SLOTS; | 123 int length = slots_ + Context::MIN_CONTEXT_SLOTS; |
| 122 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, | 124 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, |
| 123 eax, ebx, ecx, &gc, TAG_OBJECT); | 125 eax, ebx, ecx, &gc, TAG_OBJECT); |
| 124 | 126 |
| 125 // Get the function from the stack. | 127 // Get the function from the stack. |
| 126 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 128 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 127 | 129 |
| 128 // Setup the object header. | 130 // Setup the object header. |
| 129 __ mov(FieldOperand(eax, HeapObject::kMapOffset), FACTORY->context_map()); | 131 Factory* factory = masm->isolate()->factory(); |
| 132 __ mov(FieldOperand(eax, HeapObject::kMapOffset), factory->context_map()); |
| 130 __ mov(FieldOperand(eax, Context::kLengthOffset), | 133 __ mov(FieldOperand(eax, Context::kLengthOffset), |
| 131 Immediate(Smi::FromInt(length))); | 134 Immediate(Smi::FromInt(length))); |
| 132 | 135 |
| 133 // Setup the fixed slots. | 136 // Setup the fixed slots. |
| 134 __ Set(ebx, Immediate(0)); // Set to NULL. | 137 __ Set(ebx, Immediate(0)); // Set to NULL. |
| 135 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx); | 138 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx); |
| 136 __ mov(Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)), eax); | 139 __ mov(Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)), eax); |
| 137 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), ebx); | 140 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), ebx); |
| 138 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx); | 141 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx); |
| 139 | 142 |
| 140 // Copy the global object from the surrounding context. We go through the | 143 // Copy the global object from the surrounding context. We go through the |
| 141 // context in the function (ecx) to match the allocation behavior we have | 144 // context in the function (ecx) to match the allocation behavior we have |
| 142 // in the runtime system (see Heap::AllocateFunctionContext). | 145 // in the runtime system (see Heap::AllocateFunctionContext). |
| 143 __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset)); | 146 __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset)); |
| 144 __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX))); | 147 __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 145 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); | 148 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); |
| 146 | 149 |
| 147 // Initialize the rest of the slots to undefined. | 150 // Initialize the rest of the slots to undefined. |
| 148 __ mov(ebx, FACTORY->undefined_value()); | 151 __ mov(ebx, factory->undefined_value()); |
| 149 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { | 152 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { |
| 150 __ mov(Operand(eax, Context::SlotOffset(i)), ebx); | 153 __ mov(Operand(eax, Context::SlotOffset(i)), ebx); |
| 151 } | 154 } |
| 152 | 155 |
| 153 // Return and remove the on-stack parameter. | 156 // Return and remove the on-stack parameter. |
| 154 __ mov(esi, Operand(eax)); | 157 __ mov(esi, Operand(eax)); |
| 155 __ ret(1 * kPointerSize); | 158 __ ret(1 * kPointerSize); |
| 156 | 159 |
| 157 // Need to collect. Call into runtime system. | 160 // Need to collect. Call into runtime system. |
| 158 __ bind(&gc); | 161 __ bind(&gc); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 174 // Load boilerplate object into ecx and check if we need to create a | 177 // Load boilerplate object into ecx and check if we need to create a |
| 175 // boilerplate. | 178 // boilerplate. |
| 176 Label slow_case; | 179 Label slow_case; |
| 177 __ mov(ecx, Operand(esp, 3 * kPointerSize)); | 180 __ mov(ecx, Operand(esp, 3 * kPointerSize)); |
| 178 __ mov(eax, Operand(esp, 2 * kPointerSize)); | 181 __ mov(eax, Operand(esp, 2 * kPointerSize)); |
| 179 STATIC_ASSERT(kPointerSize == 4); | 182 STATIC_ASSERT(kPointerSize == 4); |
| 180 STATIC_ASSERT(kSmiTagSize == 1); | 183 STATIC_ASSERT(kSmiTagSize == 1); |
| 181 STATIC_ASSERT(kSmiTag == 0); | 184 STATIC_ASSERT(kSmiTag == 0); |
| 182 __ mov(ecx, FieldOperand(ecx, eax, times_half_pointer_size, | 185 __ mov(ecx, FieldOperand(ecx, eax, times_half_pointer_size, |
| 183 FixedArray::kHeaderSize)); | 186 FixedArray::kHeaderSize)); |
| 184 __ cmp(ecx, FACTORY->undefined_value()); | 187 Factory* factory = masm->isolate()->factory(); |
| 188 __ cmp(ecx, factory->undefined_value()); |
| 185 __ j(equal, &slow_case); | 189 __ j(equal, &slow_case); |
| 186 | 190 |
| 187 if (FLAG_debug_code) { | 191 if (FLAG_debug_code) { |
| 188 const char* message; | 192 const char* message; |
| 189 Handle<Map> expected_map; | 193 Handle<Map> expected_map; |
| 190 if (mode_ == CLONE_ELEMENTS) { | 194 if (mode_ == CLONE_ELEMENTS) { |
| 191 message = "Expected (writable) fixed array"; | 195 message = "Expected (writable) fixed array"; |
| 192 expected_map = FACTORY->fixed_array_map(); | 196 expected_map = factory->fixed_array_map(); |
| 193 } else { | 197 } else { |
| 194 ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS); | 198 ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS); |
| 195 message = "Expected copy-on-write fixed array"; | 199 message = "Expected copy-on-write fixed array"; |
| 196 expected_map = FACTORY->fixed_cow_array_map(); | 200 expected_map = factory->fixed_cow_array_map(); |
| 197 } | 201 } |
| 198 __ push(ecx); | 202 __ push(ecx); |
| 199 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset)); | 203 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset)); |
| 200 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), expected_map); | 204 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), expected_map); |
| 201 __ Assert(equal, message); | 205 __ Assert(equal, message); |
| 202 __ pop(ecx); | 206 __ pop(ecx); |
| 203 } | 207 } |
| 204 | 208 |
| 205 // Allocate both the JS array and the elements array in one big | 209 // Allocate both the JS array and the elements array in one big |
| 206 // allocation. This avoids multiple limit checks. | 210 // allocation. This avoids multiple limit checks. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 235 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); | 239 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); |
| 236 } | 240 } |
| 237 | 241 |
| 238 | 242 |
| 239 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). | 243 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). |
| 240 void ToBooleanStub::Generate(MacroAssembler* masm) { | 244 void ToBooleanStub::Generate(MacroAssembler* masm) { |
| 241 NearLabel false_result, true_result, not_string; | 245 NearLabel false_result, true_result, not_string; |
| 242 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 246 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 243 | 247 |
| 244 // 'null' => false. | 248 // 'null' => false. |
| 245 __ cmp(eax, FACTORY->null_value()); | 249 Factory* factory = masm->isolate()->factory(); |
| 250 __ cmp(eax, factory->null_value()); |
| 246 __ j(equal, &false_result); | 251 __ j(equal, &false_result); |
| 247 | 252 |
| 248 // Get the map and type of the heap object. | 253 // Get the map and type of the heap object. |
| 249 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 254 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 250 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 255 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
| 251 | 256 |
| 252 // Undetectable => false. | 257 // Undetectable => false. |
| 253 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), | 258 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), |
| 254 1 << Map::kIsUndetectable); | 259 1 << Map::kIsUndetectable); |
| 255 __ j(not_zero, &false_result); | 260 __ j(not_zero, &false_result); |
| 256 | 261 |
| 257 // JavaScript object => true. | 262 // JavaScript object => true. |
| 258 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE); | 263 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE); |
| 259 __ j(above_equal, &true_result); | 264 __ j(above_equal, &true_result); |
| 260 | 265 |
| 261 // String value => false iff empty. | 266 // String value => false iff empty. |
| 262 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE); | 267 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE); |
| 263 __ j(above_equal, ¬_string); | 268 __ j(above_equal, ¬_string); |
| 264 STATIC_ASSERT(kSmiTag == 0); | 269 STATIC_ASSERT(kSmiTag == 0); |
| 265 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0)); | 270 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0)); |
| 266 __ j(zero, &false_result); | 271 __ j(zero, &false_result); |
| 267 __ jmp(&true_result); | 272 __ jmp(&true_result); |
| 268 | 273 |
| 269 __ bind(¬_string); | 274 __ bind(¬_string); |
| 270 // HeapNumber => false iff +0, -0, or NaN. | 275 // HeapNumber => false iff +0, -0, or NaN. |
| 271 __ cmp(edx, FACTORY->heap_number_map()); | 276 __ cmp(edx, factory->heap_number_map()); |
| 272 __ j(not_equal, &true_result); | 277 __ j(not_equal, &true_result); |
| 273 __ fldz(); | 278 __ fldz(); |
| 274 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 279 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 275 __ FCmp(); | 280 __ FCmp(); |
| 276 __ j(zero, &false_result); | 281 __ j(zero, &false_result); |
| 277 // Fall through to |true_result|. | 282 // Fall through to |true_result|. |
| 278 | 283 |
| 279 // Return 1/0 for true/false in eax. | 284 // Return 1/0 for true/false in eax. |
| 280 __ bind(&true_result); | 285 __ bind(&true_result); |
| 281 __ mov(eax, 1); | 286 __ mov(eax, 1); |
| (...skipping 2232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2514 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 2519 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
| 2515 __ mov(Operand(esp, 0), eax); | 2520 __ mov(Operand(esp, 0), eax); |
| 2516 __ fild_s(Operand(esp, 0)); | 2521 __ fild_s(Operand(esp, 0)); |
| 2517 __ fst_d(Operand(esp, 0)); | 2522 __ fst_d(Operand(esp, 0)); |
| 2518 __ pop(edx); | 2523 __ pop(edx); |
| 2519 __ pop(ebx); | 2524 __ pop(ebx); |
| 2520 __ jmp(&loaded); | 2525 __ jmp(&loaded); |
| 2521 __ bind(&input_not_smi); | 2526 __ bind(&input_not_smi); |
| 2522 // Check if input is a HeapNumber. | 2527 // Check if input is a HeapNumber. |
| 2523 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2528 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2524 __ cmp(Operand(ebx), Immediate(FACTORY->heap_number_map())); | 2529 Factory* factory = masm->isolate()->factory(); |
| 2530 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); |
| 2525 __ j(not_equal, &runtime_call); | 2531 __ j(not_equal, &runtime_call); |
| 2526 // Input is a HeapNumber. Push it on the FPU stack and load its | 2532 // Input is a HeapNumber. Push it on the FPU stack and load its |
| 2527 // low and high words into ebx, edx. | 2533 // low and high words into ebx, edx. |
| 2528 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 2534 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2529 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 2535 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); |
| 2530 __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset)); | 2536 __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset)); |
| 2531 | 2537 |
| 2532 __ bind(&loaded); | 2538 __ bind(&loaded); |
| 2533 } else { // UNTAGGED. | 2539 } else { // UNTAGGED. |
| 2534 if (masm->isolate()->cpu_features()->IsSupported(SSE4_1)) { | 2540 if (masm->isolate()->cpu_features()->IsSupported(SSE4_1)) { |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2982 | 2988 |
| 2983 // Test if arg1 is a Smi. | 2989 // Test if arg1 is a Smi. |
| 2984 __ test(edx, Immediate(kSmiTagMask)); | 2990 __ test(edx, Immediate(kSmiTagMask)); |
| 2985 __ j(not_zero, &arg1_is_object); | 2991 __ j(not_zero, &arg1_is_object); |
| 2986 | 2992 |
| 2987 __ SmiUntag(edx); | 2993 __ SmiUntag(edx); |
| 2988 __ jmp(&load_arg2); | 2994 __ jmp(&load_arg2); |
| 2989 | 2995 |
| 2990 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 2996 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 2991 __ bind(&check_undefined_arg1); | 2997 __ bind(&check_undefined_arg1); |
| 2992 __ cmp(edx, FACTORY->undefined_value()); | 2998 Factory* factory = masm->isolate()->factory(); |
| 2999 __ cmp(edx, factory->undefined_value()); |
| 2993 __ j(not_equal, conversion_failure); | 3000 __ j(not_equal, conversion_failure); |
| 2994 __ mov(edx, Immediate(0)); | 3001 __ mov(edx, Immediate(0)); |
| 2995 __ jmp(&load_arg2); | 3002 __ jmp(&load_arg2); |
| 2996 | 3003 |
| 2997 __ bind(&arg1_is_object); | 3004 __ bind(&arg1_is_object); |
| 2998 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 3005 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 2999 __ cmp(ebx, FACTORY->heap_number_map()); | 3006 __ cmp(ebx, factory->heap_number_map()); |
| 3000 __ j(not_equal, &check_undefined_arg1); | 3007 __ j(not_equal, &check_undefined_arg1); |
| 3001 | 3008 |
| 3002 // Get the untagged integer version of the edx heap number in ecx. | 3009 // Get the untagged integer version of the edx heap number in ecx. |
| 3003 IntegerConvert(masm, | 3010 IntegerConvert(masm, |
| 3004 edx, | 3011 edx, |
| 3005 TypeInfo::Unknown(), | 3012 TypeInfo::Unknown(), |
| 3006 use_sse3, | 3013 use_sse3, |
| 3007 conversion_failure); | 3014 conversion_failure); |
| 3008 __ mov(edx, ecx); | 3015 __ mov(edx, ecx); |
| 3009 | 3016 |
| 3010 // Here edx has the untagged integer, eax has a Smi or a heap number. | 3017 // Here edx has the untagged integer, eax has a Smi or a heap number. |
| 3011 __ bind(&load_arg2); | 3018 __ bind(&load_arg2); |
| 3012 | 3019 |
| 3013 // Test if arg2 is a Smi. | 3020 // Test if arg2 is a Smi. |
| 3014 __ test(eax, Immediate(kSmiTagMask)); | 3021 __ test(eax, Immediate(kSmiTagMask)); |
| 3015 __ j(not_zero, &arg2_is_object); | 3022 __ j(not_zero, &arg2_is_object); |
| 3016 | 3023 |
| 3017 __ SmiUntag(eax); | 3024 __ SmiUntag(eax); |
| 3018 __ mov(ecx, eax); | 3025 __ mov(ecx, eax); |
| 3019 __ jmp(&done); | 3026 __ jmp(&done); |
| 3020 | 3027 |
| 3021 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 3028 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 3022 __ bind(&check_undefined_arg2); | 3029 __ bind(&check_undefined_arg2); |
| 3023 __ cmp(eax, FACTORY->undefined_value()); | 3030 __ cmp(eax, factory->undefined_value()); |
| 3024 __ j(not_equal, conversion_failure); | 3031 __ j(not_equal, conversion_failure); |
| 3025 __ mov(ecx, Immediate(0)); | 3032 __ mov(ecx, Immediate(0)); |
| 3026 __ jmp(&done); | 3033 __ jmp(&done); |
| 3027 | 3034 |
| 3028 __ bind(&arg2_is_object); | 3035 __ bind(&arg2_is_object); |
| 3029 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3036 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3030 __ cmp(ebx, FACTORY->heap_number_map()); | 3037 __ cmp(ebx, factory->heap_number_map()); |
| 3031 __ j(not_equal, &check_undefined_arg2); | 3038 __ j(not_equal, &check_undefined_arg2); |
| 3032 | 3039 |
| 3033 // Get the untagged integer version of the eax heap number in ecx. | 3040 // Get the untagged integer version of the eax heap number in ecx. |
| 3034 IntegerConvert(masm, | 3041 IntegerConvert(masm, |
| 3035 eax, | 3042 eax, |
| 3036 TypeInfo::Unknown(), | 3043 TypeInfo::Unknown(), |
| 3037 use_sse3, | 3044 use_sse3, |
| 3038 conversion_failure); | 3045 conversion_failure); |
| 3039 __ bind(&done); | 3046 __ bind(&done); |
| 3040 __ mov(eax, edx); | 3047 __ mov(eax, edx); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3107 __ bind(&done); | 3114 __ bind(&done); |
| 3108 } | 3115 } |
| 3109 | 3116 |
| 3110 | 3117 |
| 3111 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, | 3118 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, |
| 3112 Label* not_numbers) { | 3119 Label* not_numbers) { |
| 3113 NearLabel load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; | 3120 NearLabel load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; |
| 3114 // Load operand in edx into xmm0, or branch to not_numbers. | 3121 // Load operand in edx into xmm0, or branch to not_numbers. |
| 3115 __ test(edx, Immediate(kSmiTagMask)); | 3122 __ test(edx, Immediate(kSmiTagMask)); |
| 3116 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. | 3123 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. |
| 3117 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), FACTORY->heap_number_map()); | 3124 Factory* factory = masm->isolate()->factory(); |
| 3125 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); |
| 3118 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 3126 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
| 3119 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 3127 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 3120 __ bind(&load_eax); | 3128 __ bind(&load_eax); |
| 3121 // Load operand in eax into xmm1, or branch to not_numbers. | 3129 // Load operand in eax into xmm1, or branch to not_numbers. |
| 3122 __ test(eax, Immediate(kSmiTagMask)); | 3130 __ test(eax, Immediate(kSmiTagMask)); |
| 3123 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. | 3131 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. |
| 3124 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), FACTORY->heap_number_map()); | 3132 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); |
| 3125 __ j(equal, &load_float_eax); | 3133 __ j(equal, &load_float_eax); |
| 3126 __ jmp(not_numbers); // Argument in eax is not a number. | 3134 __ jmp(not_numbers); // Argument in eax is not a number. |
| 3127 __ bind(&load_smi_edx); | 3135 __ bind(&load_smi_edx); |
| 3128 __ SmiUntag(edx); // Untag smi before converting to float. | 3136 __ SmiUntag(edx); // Untag smi before converting to float. |
| 3129 __ cvtsi2sd(xmm0, Operand(edx)); | 3137 __ cvtsi2sd(xmm0, Operand(edx)); |
| 3130 __ SmiTag(edx); // Retag smi for heap number overwriting test. | 3138 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
| 3131 __ jmp(&load_eax); | 3139 __ jmp(&load_eax); |
| 3132 __ bind(&load_smi_eax); | 3140 __ bind(&load_smi_eax); |
| 3133 __ SmiUntag(eax); // Untag smi before converting to float. | 3141 __ SmiUntag(eax); // Untag smi before converting to float. |
| 3134 __ cvtsi2sd(xmm1, Operand(eax)); | 3142 __ cvtsi2sd(xmm1, Operand(eax)); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3232 | 3240 |
| 3233 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, | 3241 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, |
| 3234 Label* non_float, | 3242 Label* non_float, |
| 3235 Register scratch) { | 3243 Register scratch) { |
| 3236 NearLabel test_other, done; | 3244 NearLabel test_other, done; |
| 3237 // Test if both operands are floats or smi -> scratch=k_is_float; | 3245 // Test if both operands are floats or smi -> scratch=k_is_float; |
| 3238 // Otherwise scratch = k_not_float. | 3246 // Otherwise scratch = k_not_float. |
| 3239 __ test(edx, Immediate(kSmiTagMask)); | 3247 __ test(edx, Immediate(kSmiTagMask)); |
| 3240 __ j(zero, &test_other, not_taken); // argument in edx is OK | 3248 __ j(zero, &test_other, not_taken); // argument in edx is OK |
| 3241 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); | 3249 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); |
| 3242 __ cmp(scratch, FACTORY->heap_number_map()); | 3250 Factory* factory = masm->isolate()->factory(); |
| 3251 __ cmp(scratch, factory->heap_number_map()); |
| 3243 __ j(not_equal, non_float); // argument in edx is not a number -> NaN | 3252 __ j(not_equal, non_float); // argument in edx is not a number -> NaN |
| 3244 | 3253 |
| 3245 __ bind(&test_other); | 3254 __ bind(&test_other); |
| 3246 __ test(eax, Immediate(kSmiTagMask)); | 3255 __ test(eax, Immediate(kSmiTagMask)); |
| 3247 __ j(zero, &done); // argument in eax is OK | 3256 __ j(zero, &done); // argument in eax is OK |
| 3248 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); | 3257 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3249 __ cmp(scratch, FACTORY->heap_number_map()); | 3258 __ cmp(scratch, factory->heap_number_map()); |
| 3250 __ j(not_equal, non_float); // argument in eax is not a number -> NaN | 3259 __ j(not_equal, non_float); // argument in eax is not a number -> NaN |
| 3251 | 3260 |
| 3252 // Fall-through: Both operands are numbers. | 3261 // Fall-through: Both operands are numbers. |
| 3253 __ bind(&done); | 3262 __ bind(&done); |
| 3254 } | 3263 } |
| 3255 | 3264 |
| 3256 | 3265 |
| 3257 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, | 3266 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, |
| 3258 Label* non_int32) { | 3267 Label* non_int32) { |
| 3259 return; | 3268 return; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3285 __ j(overflow, &undo, not_taken); | 3294 __ j(overflow, &undo, not_taken); |
| 3286 __ StubReturn(1); | 3295 __ StubReturn(1); |
| 3287 | 3296 |
| 3288 // Try floating point case. | 3297 // Try floating point case. |
| 3289 __ bind(&try_float); | 3298 __ bind(&try_float); |
| 3290 } else if (FLAG_debug_code) { | 3299 } else if (FLAG_debug_code) { |
| 3291 __ AbortIfSmi(eax); | 3300 __ AbortIfSmi(eax); |
| 3292 } | 3301 } |
| 3293 | 3302 |
| 3294 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 3303 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3295 __ cmp(edx, FACTORY->heap_number_map()); | 3304 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); |
| 3296 __ j(not_equal, &slow); | 3305 __ j(not_equal, &slow); |
| 3297 if (overwrite_ == UNARY_OVERWRITE) { | 3306 if (overwrite_ == UNARY_OVERWRITE) { |
| 3298 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 3307 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); |
| 3299 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. | 3308 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. |
| 3300 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); | 3309 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); |
| 3301 } else { | 3310 } else { |
| 3302 __ mov(edx, Operand(eax)); | 3311 __ mov(edx, Operand(eax)); |
| 3303 // edx: operand | 3312 // edx: operand |
| 3304 __ AllocateHeapNumber(eax, ebx, ecx, &undo); | 3313 __ AllocateHeapNumber(eax, ebx, ecx, &undo); |
| 3305 // eax: allocated 'empty' number | 3314 // eax: allocated 'empty' number |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3317 __ not_(eax); | 3326 __ not_(eax); |
| 3318 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag. | 3327 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag. |
| 3319 __ ret(0); | 3328 __ ret(0); |
| 3320 __ bind(&non_smi); | 3329 __ bind(&non_smi); |
| 3321 } else if (FLAG_debug_code) { | 3330 } else if (FLAG_debug_code) { |
| 3322 __ AbortIfSmi(eax); | 3331 __ AbortIfSmi(eax); |
| 3323 } | 3332 } |
| 3324 | 3333 |
| 3325 // Check if the operand is a heap number. | 3334 // Check if the operand is a heap number. |
| 3326 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 3335 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3327 __ cmp(edx, FACTORY->heap_number_map()); | 3336 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); |
| 3328 __ j(not_equal, &slow, not_taken); | 3337 __ j(not_equal, &slow, not_taken); |
| 3329 | 3338 |
| 3330 // Convert the heap number in eax to an untagged integer in ecx. | 3339 // Convert the heap number in eax to an untagged integer in ecx. |
| 3331 IntegerConvert(masm, | 3340 IntegerConvert(masm, |
| 3332 eax, | 3341 eax, |
| 3333 TypeInfo::Unknown(), | 3342 TypeInfo::Unknown(), |
| 3334 masm->isolate()->cpu_features()->IsSupported(SSE3), | 3343 masm->isolate()->cpu_features()->IsSupported(SSE3), |
| 3335 &slow); | 3344 &slow); |
| 3336 | 3345 |
| 3337 // Do the bitwise operation and check if the result fits in a smi. | 3346 // Do the bitwise operation and check if the result fits in a smi. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3419 __ test(edx, Immediate(kSmiTagMask)); | 3428 __ test(edx, Immediate(kSmiTagMask)); |
| 3420 __ j(not_zero, &base_nonsmi); | 3429 __ j(not_zero, &base_nonsmi); |
| 3421 | 3430 |
| 3422 // Optimized version when both exponent and base are smis. | 3431 // Optimized version when both exponent and base are smis. |
| 3423 Label powi; | 3432 Label powi; |
| 3424 __ SmiUntag(edx); | 3433 __ SmiUntag(edx); |
| 3425 __ cvtsi2sd(xmm0, Operand(edx)); | 3434 __ cvtsi2sd(xmm0, Operand(edx)); |
| 3426 __ jmp(&powi); | 3435 __ jmp(&powi); |
| 3427 // exponent is smi and base is a heapnumber. | 3436 // exponent is smi and base is a heapnumber. |
| 3428 __ bind(&base_nonsmi); | 3437 __ bind(&base_nonsmi); |
| 3438 Factory* factory = masm->isolate()->factory(); |
| 3429 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3439 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3430 FACTORY->heap_number_map()); | 3440 factory->heap_number_map()); |
| 3431 __ j(not_equal, &call_runtime); | 3441 __ j(not_equal, &call_runtime); |
| 3432 | 3442 |
| 3433 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 3443 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 3434 | 3444 |
| 3435 // Optimized version of pow if exponent is a smi. | 3445 // Optimized version of pow if exponent is a smi. |
| 3436 // xmm0 contains the base. | 3446 // xmm0 contains the base. |
| 3437 __ bind(&powi); | 3447 __ bind(&powi); |
| 3438 __ SmiUntag(eax); | 3448 __ SmiUntag(eax); |
| 3439 | 3449 |
| 3440 // Save exponent in base as we need to check if exponent is negative later. | 3450 // Save exponent in base as we need to check if exponent is negative later. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3472 __ ucomisd(xmm0, xmm1); | 3482 __ ucomisd(xmm0, xmm1); |
| 3473 __ j(equal, &call_runtime); | 3483 __ j(equal, &call_runtime); |
| 3474 __ divsd(xmm3, xmm1); | 3484 __ divsd(xmm3, xmm1); |
| 3475 __ movsd(xmm1, xmm3); | 3485 __ movsd(xmm1, xmm3); |
| 3476 __ jmp(&allocate_return); | 3486 __ jmp(&allocate_return); |
| 3477 | 3487 |
| 3478 // exponent (or both) is a heapnumber - no matter what we should now work | 3488 // exponent (or both) is a heapnumber - no matter what we should now work |
| 3479 // on doubles. | 3489 // on doubles. |
| 3480 __ bind(&exponent_nonsmi); | 3490 __ bind(&exponent_nonsmi); |
| 3481 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3491 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 3482 FACTORY->heap_number_map()); | 3492 factory->heap_number_map()); |
| 3483 __ j(not_equal, &call_runtime); | 3493 __ j(not_equal, &call_runtime); |
| 3484 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 3494 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3485 // Test if exponent is nan. | 3495 // Test if exponent is nan. |
| 3486 __ ucomisd(xmm1, xmm1); | 3496 __ ucomisd(xmm1, xmm1); |
| 3487 __ j(parity_even, &call_runtime); | 3497 __ j(parity_even, &call_runtime); |
| 3488 | 3498 |
| 3489 NearLabel base_not_smi; | 3499 NearLabel base_not_smi; |
| 3490 NearLabel handle_special_cases; | 3500 NearLabel handle_special_cases; |
| 3491 __ test(edx, Immediate(kSmiTagMask)); | 3501 __ test(edx, Immediate(kSmiTagMask)); |
| 3492 __ j(not_zero, &base_not_smi); | 3502 __ j(not_zero, &base_not_smi); |
| 3493 __ SmiUntag(edx); | 3503 __ SmiUntag(edx); |
| 3494 __ cvtsi2sd(xmm0, Operand(edx)); | 3504 __ cvtsi2sd(xmm0, Operand(edx)); |
| 3495 __ jmp(&handle_special_cases); | 3505 __ jmp(&handle_special_cases); |
| 3496 | 3506 |
| 3497 __ bind(&base_not_smi); | 3507 __ bind(&base_not_smi); |
| 3498 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3508 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3499 FACTORY->heap_number_map()); | 3509 factory->heap_number_map()); |
| 3500 __ j(not_equal, &call_runtime); | 3510 __ j(not_equal, &call_runtime); |
| 3501 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 3511 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
| 3502 __ and_(ecx, HeapNumber::kExponentMask); | 3512 __ and_(ecx, HeapNumber::kExponentMask); |
| 3503 __ cmp(Operand(ecx), Immediate(HeapNumber::kExponentMask)); | 3513 __ cmp(Operand(ecx), Immediate(HeapNumber::kExponentMask)); |
| 3504 // base is NaN or +/-Infinity | 3514 // base is NaN or +/-Infinity |
| 3505 __ j(greater_equal, &call_runtime); | 3515 __ j(greater_equal, &call_runtime); |
| 3506 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 3516 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 3507 | 3517 |
| 3508 // base is in xmm0 and exponent is in xmm1. | 3518 // base is in xmm0 and exponent is in xmm1. |
| 3509 __ bind(&handle_special_cases); | 3519 __ bind(&handle_special_cases); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3687 __ j(zero, &done); | 3697 __ j(zero, &done); |
| 3688 | 3698 |
| 3689 // Get the parameters pointer from the stack. | 3699 // Get the parameters pointer from the stack. |
| 3690 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 3700 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 3691 | 3701 |
| 3692 // Setup the elements pointer in the allocated arguments object and | 3702 // Setup the elements pointer in the allocated arguments object and |
| 3693 // initialize the header in the elements fixed array. | 3703 // initialize the header in the elements fixed array. |
| 3694 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); | 3704 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); |
| 3695 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | 3705 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
| 3696 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | 3706 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
| 3697 Immediate(FACTORY->fixed_array_map())); | 3707 Immediate(masm->isolate()->factory()->fixed_array_map())); |
| 3698 | 3708 |
| 3699 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | 3709 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |
| 3700 // Untag the length for the loop below. | 3710 // Untag the length for the loop below. |
| 3701 __ SmiUntag(ecx); | 3711 __ SmiUntag(ecx); |
| 3702 | 3712 |
| 3703 // Copy the fixed array slots. | 3713 // Copy the fixed array slots. |
| 3704 NearLabel loop; | 3714 NearLabel loop; |
| 3705 __ bind(&loop); | 3715 __ bind(&loop); |
| 3706 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. | 3716 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. |
| 3707 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); | 3717 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3816 // edx: Number of capture registers | 3826 // edx: Number of capture registers |
| 3817 // Check that the fourth object is a JSArray object. | 3827 // Check that the fourth object is a JSArray object. |
| 3818 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 3828 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
| 3819 __ test(eax, Immediate(kSmiTagMask)); | 3829 __ test(eax, Immediate(kSmiTagMask)); |
| 3820 __ j(zero, &runtime); | 3830 __ j(zero, &runtime); |
| 3821 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); | 3831 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); |
| 3822 __ j(not_equal, &runtime); | 3832 __ j(not_equal, &runtime); |
| 3823 // Check that the JSArray is in fast case. | 3833 // Check that the JSArray is in fast case. |
| 3824 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); | 3834 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); |
| 3825 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); | 3835 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); |
| 3826 __ cmp(eax, FACTORY->fixed_array_map()); | 3836 Factory* factory = masm->isolate()->factory(); |
| 3837 __ cmp(eax, factory->fixed_array_map()); |
| 3827 __ j(not_equal, &runtime); | 3838 __ j(not_equal, &runtime); |
| 3828 // Check that the last match info has space for the capture registers and the | 3839 // Check that the last match info has space for the capture registers and the |
| 3829 // additional information. | 3840 // additional information. |
| 3830 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); | 3841 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); |
| 3831 __ SmiUntag(eax); | 3842 __ SmiUntag(eax); |
| 3832 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead)); | 3843 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead)); |
| 3833 __ cmp(edx, Operand(eax)); | 3844 __ cmp(edx, Operand(eax)); |
| 3834 __ j(greater, &runtime); | 3845 __ j(greater, &runtime); |
| 3835 | 3846 |
| 3836 // ecx: RegExp data (FixedArray) | 3847 // ecx: RegExp data (FixedArray) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3854 // string. In that case the subject string is just the first part of the cons | 3865 // string. In that case the subject string is just the first part of the cons |
| 3855 // string. Also in this case the first part of the cons string is known to be | 3866 // string. Also in this case the first part of the cons string is known to be |
| 3856 // a sequential string or an external string. | 3867 // a sequential string or an external string. |
| 3857 STATIC_ASSERT(kExternalStringTag != 0); | 3868 STATIC_ASSERT(kExternalStringTag != 0); |
| 3858 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); | 3869 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); |
| 3859 __ test(Operand(ebx), | 3870 __ test(Operand(ebx), |
| 3860 Immediate(kIsNotStringMask | kExternalStringTag)); | 3871 Immediate(kIsNotStringMask | kExternalStringTag)); |
| 3861 __ j(not_zero, &runtime); | 3872 __ j(not_zero, &runtime); |
| 3862 // String is a cons string. | 3873 // String is a cons string. |
| 3863 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); | 3874 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); |
| 3864 __ cmp(Operand(edx), FACTORY->empty_string()); | 3875 __ cmp(Operand(edx), factory->empty_string()); |
| 3865 __ j(not_equal, &runtime); | 3876 __ j(not_equal, &runtime); |
| 3866 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); | 3877 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
| 3867 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3878 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3868 // String is a cons string with empty second part. | 3879 // String is a cons string with empty second part. |
| 3869 // eax: first part of cons string. | 3880 // eax: first part of cons string. |
| 3870 // ebx: map of first part of cons string. | 3881 // ebx: map of first part of cons string. |
| 3871 // Is first part a flat two byte string? | 3882 // Is first part a flat two byte string? |
| 3872 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | 3883 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), |
| 3873 kStringRepresentationMask | kStringEncodingMask); | 3884 kStringRepresentationMask | kStringEncodingMask); |
| 3874 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 3885 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3993 __ mov(eax, Operand::StaticVariable(pending_exception)); | 4004 __ mov(eax, Operand::StaticVariable(pending_exception)); |
| 3994 __ cmp(edx, Operand(eax)); | 4005 __ cmp(edx, Operand(eax)); |
| 3995 __ j(equal, &runtime); | 4006 __ j(equal, &runtime); |
| 3996 // For exception, throw the exception again. | 4007 // For exception, throw the exception again. |
| 3997 | 4008 |
| 3998 // Clear the pending exception variable. | 4009 // Clear the pending exception variable. |
| 3999 __ mov(Operand::StaticVariable(pending_exception), edx); | 4010 __ mov(Operand::StaticVariable(pending_exception), edx); |
| 4000 | 4011 |
| 4001 // Special handling of termination exceptions which are uncatchable | 4012 // Special handling of termination exceptions which are uncatchable |
| 4002 // by javascript code. | 4013 // by javascript code. |
| 4003 __ cmp(eax, FACTORY->termination_exception()); | 4014 __ cmp(eax, factory->termination_exception()); |
| 4004 Label throw_termination_exception; | 4015 Label throw_termination_exception; |
| 4005 __ j(equal, &throw_termination_exception); | 4016 __ j(equal, &throw_termination_exception); |
| 4006 | 4017 |
| 4007 // Handle normal exception by following handler chain. | 4018 // Handle normal exception by following handler chain. |
| 4008 __ Throw(eax); | 4019 __ Throw(eax); |
| 4009 | 4020 |
| 4010 __ bind(&throw_termination_exception); | 4021 __ bind(&throw_termination_exception); |
| 4011 __ ThrowUncatchable(TERMINATION, eax); | 4022 __ ThrowUncatchable(TERMINATION, eax); |
| 4012 | 4023 |
| 4013 __ bind(&failure); | 4024 __ bind(&failure); |
| 4014 // For failure to match, return null. | 4025 // For failure to match, return null. |
| 4015 __ mov(Operand(eax), FACTORY->null_value()); | 4026 __ mov(Operand(eax), factory->null_value()); |
| 4016 __ ret(4 * kPointerSize); | 4027 __ ret(4 * kPointerSize); |
| 4017 | 4028 |
| 4018 // Load RegExp data. | 4029 // Load RegExp data. |
| 4019 __ bind(&success); | 4030 __ bind(&success); |
| 4020 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 4031 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
| 4021 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 4032 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
| 4022 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); | 4033 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 4023 // Calculate number of capture registers (number_of_captures + 1) * 2. | 4034 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 4024 STATIC_ASSERT(kSmiTag == 0); | 4035 STATIC_ASSERT(kSmiTag == 0); |
| 4025 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 4036 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4106 edx, // Scratch register | 4117 edx, // Scratch register |
| 4107 &slowcase, | 4118 &slowcase, |
| 4108 TAG_OBJECT); | 4119 TAG_OBJECT); |
| 4109 // eax: Start of allocated area, object-tagged. | 4120 // eax: Start of allocated area, object-tagged. |
| 4110 | 4121 |
| 4111 // Set JSArray map to global.regexp_result_map(). | 4122 // Set JSArray map to global.regexp_result_map(). |
| 4112 // Set empty properties FixedArray. | 4123 // Set empty properties FixedArray. |
| 4113 // Set elements to point to FixedArray allocated right after the JSArray. | 4124 // Set elements to point to FixedArray allocated right after the JSArray. |
| 4114 // Interleave operations for better latency. | 4125 // Interleave operations for better latency. |
| 4115 __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX)); | 4126 __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX)); |
| 4116 __ mov(ecx, Immediate(FACTORY->empty_fixed_array())); | 4127 Factory* factory = masm->isolate()->factory(); |
| 4128 __ mov(ecx, Immediate(factory->empty_fixed_array())); |
| 4117 __ lea(ebx, Operand(eax, JSRegExpResult::kSize)); | 4129 __ lea(ebx, Operand(eax, JSRegExpResult::kSize)); |
| 4118 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset)); | 4130 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset)); |
| 4119 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); | 4131 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); |
| 4120 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); | 4132 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); |
| 4121 __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX)); | 4133 __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX)); |
| 4122 __ mov(FieldOperand(eax, HeapObject::kMapOffset), edx); | 4134 __ mov(FieldOperand(eax, HeapObject::kMapOffset), edx); |
| 4123 | 4135 |
| 4124 // Set input, index and length fields from arguments. | 4136 // Set input, index and length fields from arguments. |
| 4125 __ mov(ecx, Operand(esp, kPointerSize * 1)); | 4137 __ mov(ecx, Operand(esp, kPointerSize * 1)); |
| 4126 __ mov(FieldOperand(eax, JSRegExpResult::kInputOffset), ecx); | 4138 __ mov(FieldOperand(eax, JSRegExpResult::kInputOffset), ecx); |
| 4127 __ mov(ecx, Operand(esp, kPointerSize * 2)); | 4139 __ mov(ecx, Operand(esp, kPointerSize * 2)); |
| 4128 __ mov(FieldOperand(eax, JSRegExpResult::kIndexOffset), ecx); | 4140 __ mov(FieldOperand(eax, JSRegExpResult::kIndexOffset), ecx); |
| 4129 __ mov(ecx, Operand(esp, kPointerSize * 3)); | 4141 __ mov(ecx, Operand(esp, kPointerSize * 3)); |
| 4130 __ mov(FieldOperand(eax, JSArray::kLengthOffset), ecx); | 4142 __ mov(FieldOperand(eax, JSArray::kLengthOffset), ecx); |
| 4131 | 4143 |
| 4132 // Fill out the elements FixedArray. | 4144 // Fill out the elements FixedArray. |
| 4133 // eax: JSArray. | 4145 // eax: JSArray. |
| 4134 // ebx: FixedArray. | 4146 // ebx: FixedArray. |
| 4135 // ecx: Number of elements in array, as smi. | 4147 // ecx: Number of elements in array, as smi. |
| 4136 | 4148 |
| 4137 // Set map. | 4149 // Set map. |
| 4138 __ mov(FieldOperand(ebx, HeapObject::kMapOffset), | 4150 __ mov(FieldOperand(ebx, HeapObject::kMapOffset), |
| 4139 Immediate(FACTORY->fixed_array_map())); | 4151 Immediate(factory->fixed_array_map())); |
| 4140 // Set length. | 4152 // Set length. |
| 4141 __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx); | 4153 __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx); |
| 4142 // Fill contents of fixed-array with the-hole. | 4154 // Fill contents of fixed-array with the-hole. |
| 4143 __ SmiUntag(ecx); | 4155 __ SmiUntag(ecx); |
| 4144 __ mov(edx, Immediate(FACTORY->the_hole_value())); | 4156 __ mov(edx, Immediate(factory->the_hole_value())); |
| 4145 __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize)); | 4157 __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize)); |
| 4146 // Fill fixed array elements with hole. | 4158 // Fill fixed array elements with hole. |
| 4147 // eax: JSArray. | 4159 // eax: JSArray. |
| 4148 // ecx: Number of elements to fill. | 4160 // ecx: Number of elements to fill. |
| 4149 // ebx: Start of elements in FixedArray. | 4161 // ebx: Start of elements in FixedArray. |
| 4150 // edx: the hole. | 4162 // edx: the hole. |
| 4151 Label loop; | 4163 Label loop; |
| 4152 __ test(ecx, Operand(ecx)); | 4164 __ test(ecx, Operand(ecx)); |
| 4153 __ bind(&loop); | 4165 __ bind(&loop); |
| 4154 __ j(less_equal, &done); // Jump if ecx is negative or zero. | 4166 __ j(less_equal, &done); // Jump if ecx is negative or zero. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4200 } else { | 4212 } else { |
| 4201 NearLabel not_smi, hash_calculated; | 4213 NearLabel not_smi, hash_calculated; |
| 4202 STATIC_ASSERT(kSmiTag == 0); | 4214 STATIC_ASSERT(kSmiTag == 0); |
| 4203 __ test(object, Immediate(kSmiTagMask)); | 4215 __ test(object, Immediate(kSmiTagMask)); |
| 4204 __ j(not_zero, ¬_smi); | 4216 __ j(not_zero, ¬_smi); |
| 4205 __ mov(scratch, object); | 4217 __ mov(scratch, object); |
| 4206 __ SmiUntag(scratch); | 4218 __ SmiUntag(scratch); |
| 4207 __ jmp(&smi_hash_calculated); | 4219 __ jmp(&smi_hash_calculated); |
| 4208 __ bind(¬_smi); | 4220 __ bind(¬_smi); |
| 4209 __ cmp(FieldOperand(object, HeapObject::kMapOffset), | 4221 __ cmp(FieldOperand(object, HeapObject::kMapOffset), |
| 4210 FACTORY->heap_number_map()); | 4222 masm->isolate()->factory()->heap_number_map()); |
| 4211 __ j(not_equal, not_found); | 4223 __ j(not_equal, not_found); |
| 4212 STATIC_ASSERT(8 == kDoubleSize); | 4224 STATIC_ASSERT(8 == kDoubleSize); |
| 4213 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); | 4225 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); |
| 4214 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); | 4226 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); |
| 4215 // Object is heap number and hash is now in scratch. Calculate cache index. | 4227 // Object is heap number and hash is now in scratch. Calculate cache index. |
| 4216 __ and_(scratch, Operand(mask)); | 4228 __ and_(scratch, Operand(mask)); |
| 4217 Register index = scratch; | 4229 Register index = scratch; |
| 4218 Register probe = mask; | 4230 Register probe = mask; |
| 4219 __ mov(probe, | 4231 __ mov(probe, |
| 4220 FieldOperand(number_string_cache, | 4232 FieldOperand(number_string_cache, |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4317 // for NaN and undefined. | 4329 // for NaN and undefined. |
| 4318 { | 4330 { |
| 4319 Label not_identical; | 4331 Label not_identical; |
| 4320 __ cmp(eax, Operand(edx)); | 4332 __ cmp(eax, Operand(edx)); |
| 4321 __ j(not_equal, ¬_identical); | 4333 __ j(not_equal, ¬_identical); |
| 4322 | 4334 |
| 4323 if (cc_ != equal) { | 4335 if (cc_ != equal) { |
| 4324 // Check for undefined. undefined OP undefined is false even though | 4336 // Check for undefined. undefined OP undefined is false even though |
| 4325 // undefined == undefined. | 4337 // undefined == undefined. |
| 4326 NearLabel check_for_nan; | 4338 NearLabel check_for_nan; |
| 4327 __ cmp(edx, FACTORY->undefined_value()); | 4339 __ cmp(edx, masm->isolate()->factory()->undefined_value()); |
| 4328 __ j(not_equal, &check_for_nan); | 4340 __ j(not_equal, &check_for_nan); |
| 4329 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); | 4341 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
| 4330 __ ret(0); | 4342 __ ret(0); |
| 4331 __ bind(&check_for_nan); | 4343 __ bind(&check_for_nan); |
| 4332 } | 4344 } |
| 4333 | 4345 |
| 4334 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(), | 4346 // Test for NaN. Sadly, we can't just compare to factory->nan_value(), |
| 4335 // so we do the second best thing - test it ourselves. | 4347 // so we do the second best thing - test it ourselves. |
| 4336 // Note: if cc_ != equal, never_nan_nan_ is not used. | 4348 // Note: if cc_ != equal, never_nan_nan_ is not used. |
| 4337 if (never_nan_nan_ && (cc_ == equal)) { | 4349 if (never_nan_nan_ && (cc_ == equal)) { |
| 4338 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 4350 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 4339 __ ret(0); | 4351 __ ret(0); |
| 4340 } else { | 4352 } else { |
| 4341 NearLabel heap_number; | 4353 NearLabel heap_number; |
| 4342 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 4354 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 4343 Immediate(FACTORY->heap_number_map())); | 4355 Immediate(masm->isolate()->factory()->heap_number_map())); |
| 4344 __ j(equal, &heap_number); | 4356 __ j(equal, &heap_number); |
| 4345 if (cc_ != equal) { | 4357 if (cc_ != equal) { |
| 4346 // Call runtime on identical JSObjects. Otherwise return equal. | 4358 // Call runtime on identical JSObjects. Otherwise return equal. |
| 4347 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 4359 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
| 4348 __ j(above_equal, ¬_identical); | 4360 __ j(above_equal, ¬_identical); |
| 4349 } | 4361 } |
| 4350 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 4362 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 4351 __ ret(0); | 4363 __ ret(0); |
| 4352 | 4364 |
| 4353 __ bind(&heap_number); | 4365 __ bind(&heap_number); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4410 // ecx still holds eax & kSmiTag, which is either zero or one. | 4422 // ecx still holds eax & kSmiTag, which is either zero or one. |
| 4411 __ sub(Operand(ecx), Immediate(0x01)); | 4423 __ sub(Operand(ecx), Immediate(0x01)); |
| 4412 __ mov(ebx, edx); | 4424 __ mov(ebx, edx); |
| 4413 __ xor_(ebx, Operand(eax)); | 4425 __ xor_(ebx, Operand(eax)); |
| 4414 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. | 4426 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. |
| 4415 __ xor_(ebx, Operand(eax)); | 4427 __ xor_(ebx, Operand(eax)); |
| 4416 // if eax was smi, ebx is now edx, else eax. | 4428 // if eax was smi, ebx is now edx, else eax. |
| 4417 | 4429 |
| 4418 // Check if the non-smi operand is a heap number. | 4430 // Check if the non-smi operand is a heap number. |
| 4419 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 4431 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 4420 Immediate(FACTORY->heap_number_map())); | 4432 Immediate(masm->isolate()->factory()->heap_number_map())); |
| 4421 // If heap number, handle it in the slow case. | 4433 // If heap number, handle it in the slow case. |
| 4422 __ j(equal, &slow); | 4434 __ j(equal, &slow); |
| 4423 // Return non-equal (ebx is not zero) | 4435 // Return non-equal (ebx is not zero) |
| 4424 __ mov(eax, ebx); | 4436 __ mov(eax, ebx); |
| 4425 __ ret(0); | 4437 __ ret(0); |
| 4426 | 4438 |
| 4427 __ bind(¬_smis); | 4439 __ bind(¬_smis); |
| 4428 // If either operand is a JSObject or an oddball value, then they are not | 4440 // If either operand is a JSObject or an oddball value, then they are not |
| 4429 // equal since their pointers are different | 4441 // equal since their pointers are different |
| 4430 // There is no test for undetectability in strict equality. | 4442 // There is no test for undetectability in strict equality. |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4742 // Result is in eax or edx:eax - do not destroy these registers! | 4754 // Result is in eax or edx:eax - do not destroy these registers! |
| 4743 | 4755 |
| 4744 if (always_allocate_scope) { | 4756 if (always_allocate_scope) { |
| 4745 __ dec(Operand::StaticVariable(scope_depth)); | 4757 __ dec(Operand::StaticVariable(scope_depth)); |
| 4746 } | 4758 } |
| 4747 | 4759 |
| 4748 // Make sure we're not trying to return 'the hole' from the runtime | 4760 // Make sure we're not trying to return 'the hole' from the runtime |
| 4749 // call as this may lead to crashes in the IC code later. | 4761 // call as this may lead to crashes in the IC code later. |
| 4750 if (FLAG_debug_code) { | 4762 if (FLAG_debug_code) { |
| 4751 NearLabel okay; | 4763 NearLabel okay; |
| 4752 __ cmp(eax, FACTORY->the_hole_value()); | 4764 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); |
| 4753 __ j(not_equal, &okay); | 4765 __ j(not_equal, &okay); |
| 4754 __ int3(); | 4766 __ int3(); |
| 4755 __ bind(&okay); | 4767 __ bind(&okay); |
| 4756 } | 4768 } |
| 4757 | 4769 |
| 4758 // Check for failure result. | 4770 // Check for failure result. |
| 4759 Label failure_returned; | 4771 Label failure_returned; |
| 4760 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 4772 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
| 4761 __ lea(ecx, Operand(eax, 1)); | 4773 __ lea(ecx, Operand(eax, 1)); |
| 4762 // Lower 2 bits of ecx are 0 iff eax has failure tag. | 4774 // Lower 2 bits of ecx are 0 iff eax has failure tag. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4800 | 4812 |
| 4801 // Retrieve the pending exception and clear the variable. | 4813 // Retrieve the pending exception and clear the variable. |
| 4802 ExternalReference the_hole_location = | 4814 ExternalReference the_hole_location = |
| 4803 ExternalReference::the_hole_value_location(masm->isolate()); | 4815 ExternalReference::the_hole_value_location(masm->isolate()); |
| 4804 __ mov(eax, Operand::StaticVariable(pending_exception_address)); | 4816 __ mov(eax, Operand::StaticVariable(pending_exception_address)); |
| 4805 __ mov(edx, Operand::StaticVariable(the_hole_location)); | 4817 __ mov(edx, Operand::StaticVariable(the_hole_location)); |
| 4806 __ mov(Operand::StaticVariable(pending_exception_address), edx); | 4818 __ mov(Operand::StaticVariable(pending_exception_address), edx); |
| 4807 | 4819 |
| 4808 // Special handling of termination exceptions which are uncatchable | 4820 // Special handling of termination exceptions which are uncatchable |
| 4809 // by javascript code. | 4821 // by javascript code. |
| 4810 __ cmp(eax, FACTORY->termination_exception()); | 4822 __ cmp(eax, masm->isolate()->factory()->termination_exception()); |
| 4811 __ j(equal, throw_termination_exception); | 4823 __ j(equal, throw_termination_exception); |
| 4812 | 4824 |
| 4813 // Handle normal exception. | 4825 // Handle normal exception. |
| 4814 __ jmp(throw_normal_exception); | 4826 __ jmp(throw_normal_exception); |
| 4815 | 4827 |
| 4816 // Retry. | 4828 // Retry. |
| 4817 __ bind(&retry); | 4829 __ bind(&retry); |
| 4818 } | 4830 } |
| 4819 | 4831 |
| 4820 | 4832 |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5101 __ mov(Operand(scratch, kDeltaToCmpImmediate), map); | 5113 __ mov(Operand(scratch, kDeltaToCmpImmediate), map); |
| 5102 } | 5114 } |
| 5103 | 5115 |
| 5104 // Loop through the prototype chain of the object looking for the function | 5116 // Loop through the prototype chain of the object looking for the function |
| 5105 // prototype. | 5117 // prototype. |
| 5106 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); | 5118 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); |
| 5107 NearLabel loop, is_instance, is_not_instance; | 5119 NearLabel loop, is_instance, is_not_instance; |
| 5108 __ bind(&loop); | 5120 __ bind(&loop); |
| 5109 __ cmp(scratch, Operand(prototype)); | 5121 __ cmp(scratch, Operand(prototype)); |
| 5110 __ j(equal, &is_instance); | 5122 __ j(equal, &is_instance); |
| 5111 __ cmp(Operand(scratch), Immediate(FACTORY->null_value())); | 5123 Factory* factory = masm->isolate()->factory(); |
| 5124 __ cmp(Operand(scratch), Immediate(factory->null_value())); |
| 5112 __ j(equal, &is_not_instance); | 5125 __ j(equal, &is_not_instance); |
| 5113 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 5126 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 5114 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); | 5127 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
| 5115 __ jmp(&loop); | 5128 __ jmp(&loop); |
| 5116 | 5129 |
| 5117 __ bind(&is_instance); | 5130 __ bind(&is_instance); |
| 5118 if (!HasCallSiteInlineCheck()) { | 5131 if (!HasCallSiteInlineCheck()) { |
| 5119 __ Set(eax, Immediate(0)); | 5132 __ Set(eax, Immediate(0)); |
| 5120 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 5133 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
| 5121 __ mov(Operand::StaticArray(scratch, | 5134 __ mov(Operand::StaticArray(scratch, |
| 5122 times_pointer_size, roots_address), eax); | 5135 times_pointer_size, roots_address), eax); |
| 5123 } else { | 5136 } else { |
| 5124 // Get return address and delta to inlined map check. | 5137 // Get return address and delta to inlined map check. |
| 5125 __ mov(eax, FACTORY->true_value()); | 5138 __ mov(eax, factory->true_value()); |
| 5126 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5139 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
| 5127 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5140 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
| 5128 if (FLAG_debug_code) { | 5141 if (FLAG_debug_code) { |
| 5129 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 5142 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
| 5130 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); | 5143 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); |
| 5131 } | 5144 } |
| 5132 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 5145 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
| 5133 if (!ReturnTrueFalseObject()) { | 5146 if (!ReturnTrueFalseObject()) { |
| 5134 __ Set(eax, Immediate(0)); | 5147 __ Set(eax, Immediate(0)); |
| 5135 } | 5148 } |
| 5136 } | 5149 } |
| 5137 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5150 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 5138 | 5151 |
| 5139 __ bind(&is_not_instance); | 5152 __ bind(&is_not_instance); |
| 5140 if (!HasCallSiteInlineCheck()) { | 5153 if (!HasCallSiteInlineCheck()) { |
| 5141 __ Set(eax, Immediate(Smi::FromInt(1))); | 5154 __ Set(eax, Immediate(Smi::FromInt(1))); |
| 5142 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 5155 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
| 5143 __ mov(Operand::StaticArray( | 5156 __ mov(Operand::StaticArray( |
| 5144 scratch, times_pointer_size, roots_address), eax); | 5157 scratch, times_pointer_size, roots_address), eax); |
| 5145 } else { | 5158 } else { |
| 5146 // Get return address and delta to inlined map check. | 5159 // Get return address and delta to inlined map check. |
| 5147 __ mov(eax, FACTORY->false_value()); | 5160 __ mov(eax, factory->false_value()); |
| 5148 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5161 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
| 5149 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5162 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
| 5150 if (FLAG_debug_code) { | 5163 if (FLAG_debug_code) { |
| 5151 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 5164 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
| 5152 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); | 5165 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); |
| 5153 } | 5166 } |
| 5154 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 5167 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
| 5155 if (!ReturnTrueFalseObject()) { | 5168 if (!ReturnTrueFalseObject()) { |
| 5156 __ Set(eax, Immediate(Smi::FromInt(1))); | 5169 __ Set(eax, Immediate(Smi::FromInt(1))); |
| 5157 } | 5170 } |
| 5158 } | 5171 } |
| 5159 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5172 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 5160 | 5173 |
| 5161 Label object_not_null, object_not_null_or_smi; | 5174 Label object_not_null, object_not_null_or_smi; |
| 5162 __ bind(¬_js_object); | 5175 __ bind(¬_js_object); |
| 5163 // Before null, smi and string value checks, check that the rhs is a function | 5176 // Before null, smi and string value checks, check that the rhs is a function |
| 5164 // as for a non-function rhs an exception needs to be thrown. | 5177 // as for a non-function rhs an exception needs to be thrown. |
| 5165 __ test(function, Immediate(kSmiTagMask)); | 5178 __ test(function, Immediate(kSmiTagMask)); |
| 5166 __ j(zero, &slow, not_taken); | 5179 __ j(zero, &slow, not_taken); |
| 5167 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); | 5180 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
| 5168 __ j(not_equal, &slow, not_taken); | 5181 __ j(not_equal, &slow, not_taken); |
| 5169 | 5182 |
| 5170 // Null is not instance of anything. | 5183 // Null is not instance of anything. |
| 5171 __ cmp(object, FACTORY->null_value()); | 5184 __ cmp(object, factory->null_value()); |
| 5172 __ j(not_equal, &object_not_null); | 5185 __ j(not_equal, &object_not_null); |
| 5173 __ Set(eax, Immediate(Smi::FromInt(1))); | 5186 __ Set(eax, Immediate(Smi::FromInt(1))); |
| 5174 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5187 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 5175 | 5188 |
| 5176 __ bind(&object_not_null); | 5189 __ bind(&object_not_null); |
| 5177 // Smi values is not instance of anything. | 5190 // Smi values is not instance of anything. |
| 5178 __ test(object, Immediate(kSmiTagMask)); | 5191 __ test(object, Immediate(kSmiTagMask)); |
| 5179 __ j(not_zero, &object_not_null_or_smi, not_taken); | 5192 __ j(not_zero, &object_not_null_or_smi, not_taken); |
| 5180 __ Set(eax, Immediate(Smi::FromInt(1))); | 5193 __ Set(eax, Immediate(Smi::FromInt(1))); |
| 5181 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5194 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5202 } else { | 5215 } else { |
| 5203 // Call the builtin and convert 0/1 to true/false. | 5216 // Call the builtin and convert 0/1 to true/false. |
| 5204 __ EnterInternalFrame(); | 5217 __ EnterInternalFrame(); |
| 5205 __ push(object); | 5218 __ push(object); |
| 5206 __ push(function); | 5219 __ push(function); |
| 5207 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); | 5220 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); |
| 5208 __ LeaveInternalFrame(); | 5221 __ LeaveInternalFrame(); |
| 5209 NearLabel true_value, done; | 5222 NearLabel true_value, done; |
| 5210 __ test(eax, Operand(eax)); | 5223 __ test(eax, Operand(eax)); |
| 5211 __ j(zero, &true_value); | 5224 __ j(zero, &true_value); |
| 5212 __ mov(eax, FACTORY->false_value()); | 5225 __ mov(eax, factory->false_value()); |
| 5213 __ jmp(&done); | 5226 __ jmp(&done); |
| 5214 __ bind(&true_value); | 5227 __ bind(&true_value); |
| 5215 __ mov(eax, FACTORY->true_value()); | 5228 __ mov(eax, factory->true_value()); |
| 5216 __ bind(&done); | 5229 __ bind(&done); |
| 5217 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5230 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 5218 } | 5231 } |
| 5219 } | 5232 } |
| 5220 | 5233 |
| 5221 | 5234 |
| 5222 Register InstanceofStub::left() { return eax; } | 5235 Register InstanceofStub::left() { return eax; } |
| 5223 | 5236 |
| 5224 | 5237 |
| 5225 Register InstanceofStub::right() { return edx; } | 5238 Register InstanceofStub::right() { return edx; } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5334 // Handle non-flat strings. | 5347 // Handle non-flat strings. |
| 5335 __ test(result_, Immediate(kIsConsStringMask)); | 5348 __ test(result_, Immediate(kIsConsStringMask)); |
| 5336 __ j(zero, &call_runtime_); | 5349 __ j(zero, &call_runtime_); |
| 5337 | 5350 |
| 5338 // ConsString. | 5351 // ConsString. |
| 5339 // Check whether the right hand side is the empty string (i.e. if | 5352 // Check whether the right hand side is the empty string (i.e. if |
| 5340 // this is really a flat string in a cons string). If that is not | 5353 // this is really a flat string in a cons string). If that is not |
| 5341 // the case we would rather go to the runtime system now to flatten | 5354 // the case we would rather go to the runtime system now to flatten |
| 5342 // the string. | 5355 // the string. |
| 5343 __ cmp(FieldOperand(object_, ConsString::kSecondOffset), | 5356 __ cmp(FieldOperand(object_, ConsString::kSecondOffset), |
| 5344 Immediate(FACTORY->empty_string())); | 5357 Immediate(masm->isolate()->factory()->empty_string())); |
| 5345 __ j(not_equal, &call_runtime_); | 5358 __ j(not_equal, &call_runtime_); |
| 5346 // Get the first of the two strings and load its instance type. | 5359 // Get the first of the two strings and load its instance type. |
| 5347 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset)); | 5360 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset)); |
| 5348 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 5361 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
| 5349 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 5362 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
| 5350 // If the first cons component is also non-flat, then go to runtime. | 5363 // If the first cons component is also non-flat, then go to runtime. |
| 5351 STATIC_ASSERT(kSeqStringTag == 0); | 5364 STATIC_ASSERT(kSeqStringTag == 0); |
| 5352 __ test(result_, Immediate(kStringRepresentationMask)); | 5365 __ test(result_, Immediate(kStringRepresentationMask)); |
| 5353 __ j(not_zero, &call_runtime_); | 5366 __ j(not_zero, &call_runtime_); |
| 5354 | 5367 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 5379 } | 5392 } |
| 5380 | 5393 |
| 5381 | 5394 |
| 5382 void StringCharCodeAtGenerator::GenerateSlow( | 5395 void StringCharCodeAtGenerator::GenerateSlow( |
| 5383 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { | 5396 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { |
| 5384 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); | 5397 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); |
| 5385 | 5398 |
| 5386 // Index is not a smi. | 5399 // Index is not a smi. |
| 5387 __ bind(&index_not_smi_); | 5400 __ bind(&index_not_smi_); |
| 5388 // If index is a heap number, try converting it to an integer. | 5401 // If index is a heap number, try converting it to an integer. |
| 5389 __ CheckMap(index_, FACTORY->heap_number_map(), index_not_number_, true); | 5402 __ CheckMap(index_, |
| 5403 masm->isolate()->factory()->heap_number_map(), |
| 5404 index_not_number_, |
| 5405 true); |
| 5390 call_helper.BeforeCall(masm); | 5406 call_helper.BeforeCall(masm); |
| 5391 __ push(object_); | 5407 __ push(object_); |
| 5392 __ push(index_); | 5408 __ push(index_); |
| 5393 __ push(index_); // Consumed by runtime conversion function. | 5409 __ push(index_); // Consumed by runtime conversion function. |
| 5394 if (index_flags_ == STRING_INDEX_IS_NUMBER) { | 5410 if (index_flags_ == STRING_INDEX_IS_NUMBER) { |
| 5395 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); | 5411 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); |
| 5396 } else { | 5412 } else { |
| 5397 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); | 5413 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); |
| 5398 // NumberToSmi discards numbers that are not exact integers. | 5414 // NumberToSmi discards numbers that are not exact integers. |
| 5399 __ CallRuntime(Runtime::kNumberToSmi, 1); | 5415 __ CallRuntime(Runtime::kNumberToSmi, 1); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5440 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { | 5456 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { |
| 5441 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 5457 // Fast case of Heap::LookupSingleCharacterStringFromCode. |
| 5442 STATIC_ASSERT(kSmiTag == 0); | 5458 STATIC_ASSERT(kSmiTag == 0); |
| 5443 STATIC_ASSERT(kSmiShiftSize == 0); | 5459 STATIC_ASSERT(kSmiShiftSize == 0); |
| 5444 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); | 5460 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); |
| 5445 __ test(code_, | 5461 __ test(code_, |
| 5446 Immediate(kSmiTagMask | | 5462 Immediate(kSmiTagMask | |
| 5447 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); | 5463 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); |
| 5448 __ j(not_zero, &slow_case_, not_taken); | 5464 __ j(not_zero, &slow_case_, not_taken); |
| 5449 | 5465 |
| 5450 __ Set(result_, Immediate(FACTORY->single_character_string_cache())); | 5466 Factory* factory = masm->isolate()->factory(); |
| 5467 __ Set(result_, Immediate(factory->single_character_string_cache())); |
| 5451 STATIC_ASSERT(kSmiTag == 0); | 5468 STATIC_ASSERT(kSmiTag == 0); |
| 5452 STATIC_ASSERT(kSmiTagSize == 1); | 5469 STATIC_ASSERT(kSmiTagSize == 1); |
| 5453 STATIC_ASSERT(kSmiShiftSize == 0); | 5470 STATIC_ASSERT(kSmiShiftSize == 0); |
| 5454 // At this point code register contains smi tagged ascii char code. | 5471 // At this point code register contains smi tagged ascii char code. |
| 5455 __ mov(result_, FieldOperand(result_, | 5472 __ mov(result_, FieldOperand(result_, |
| 5456 code_, times_half_pointer_size, | 5473 code_, times_half_pointer_size, |
| 5457 FixedArray::kHeaderSize)); | 5474 FixedArray::kHeaderSize)); |
| 5458 __ cmp(result_, FACTORY->undefined_value()); | 5475 __ cmp(result_, factory->undefined_value()); |
| 5459 __ j(equal, &slow_case_, not_taken); | 5476 __ j(equal, &slow_case_, not_taken); |
| 5460 __ bind(&exit_); | 5477 __ bind(&exit_); |
| 5461 } | 5478 } |
| 5462 | 5479 |
| 5463 | 5480 |
| 5464 void StringCharFromCodeGenerator::GenerateSlow( | 5481 void StringCharFromCodeGenerator::GenerateSlow( |
| 5465 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { | 5482 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { |
| 5466 __ Abort("Unexpected fallthrough to CharFromCode slow case"); | 5483 __ Abort("Unexpected fallthrough to CharFromCode slow case"); |
| 5467 | 5484 |
| 5468 __ bind(&slow_case_); | 5485 __ bind(&slow_case_); |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5976 // Load the entry from the symbol table. | 5993 // Load the entry from the symbol table. |
| 5977 Register candidate = scratch; // Scratch register contains candidate. | 5994 Register candidate = scratch; // Scratch register contains candidate. |
| 5978 STATIC_ASSERT(SymbolTable::kEntrySize == 1); | 5995 STATIC_ASSERT(SymbolTable::kEntrySize == 1); |
| 5979 __ mov(candidate, | 5996 __ mov(candidate, |
| 5980 FieldOperand(symbol_table, | 5997 FieldOperand(symbol_table, |
| 5981 scratch, | 5998 scratch, |
| 5982 times_pointer_size, | 5999 times_pointer_size, |
| 5983 SymbolTable::kElementsStartOffset)); | 6000 SymbolTable::kElementsStartOffset)); |
| 5984 | 6001 |
| 5985 // If entry is undefined no string with this hash can be found. | 6002 // If entry is undefined no string with this hash can be found. |
| 5986 __ cmp(candidate, FACTORY->undefined_value()); | 6003 Factory* factory = masm->isolate()->factory(); |
| 6004 __ cmp(candidate, factory->undefined_value()); |
| 5987 __ j(equal, not_found); | 6005 __ j(equal, not_found); |
| 5988 __ cmp(candidate, FACTORY->null_value()); | 6006 __ cmp(candidate, factory->null_value()); |
| 5989 __ j(equal, &next_probe[i]); | 6007 __ j(equal, &next_probe[i]); |
| 5990 | 6008 |
| 5991 // If length is not 2 the string is not a candidate. | 6009 // If length is not 2 the string is not a candidate. |
| 5992 __ cmp(FieldOperand(candidate, String::kLengthOffset), | 6010 __ cmp(FieldOperand(candidate, String::kLengthOffset), |
| 5993 Immediate(Smi::FromInt(2))); | 6011 Immediate(Smi::FromInt(2))); |
| 5994 __ j(not_equal, &next_probe[i]); | 6012 __ j(not_equal, &next_probe[i]); |
| 5995 | 6013 |
| 5996 // As we are out of registers save the mask on the stack and use that | 6014 // As we are out of registers save the mask on the stack and use that |
| 5997 // register as a temporary. | 6015 // register as a temporary. |
| 5998 __ push(mask); | 6016 __ push(mask); |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6489 // Do a tail call to the rewritten stub. | 6507 // Do a tail call to the rewritten stub. |
| 6490 __ jmp(Operand(edi)); | 6508 __ jmp(Operand(edi)); |
| 6491 } | 6509 } |
| 6492 | 6510 |
| 6493 | 6511 |
| 6494 #undef __ | 6512 #undef __ |
| 6495 | 6513 |
| 6496 } } // namespace v8::internal | 6514 } } // namespace v8::internal |
| 6497 | 6515 |
| 6498 #endif // V8_TARGET_ARCH_IA32 | 6516 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |