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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 6880010: Merge (7265, 7271] from bleeding_edge to experimental/gc branch.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #if defined(V8_TARGET_ARCH_IA32) 30 #if defined(V8_TARGET_ARCH_IA32)
31 31
32 #include "code-stubs.h" 32 #include "code-stubs.h"
33 #include "bootstrapper.h" 33 #include "bootstrapper.h"
34 #include "jsregexp.h" 34 #include "jsregexp.h"
35 #include "isolate.h"
35 #include "regexp-macro-assembler.h" 36 #include "regexp-macro-assembler.h"
36 37
37 namespace v8 { 38 namespace v8 {
38 namespace internal { 39 namespace internal {
39 40
40 #define __ ACCESS_MASM(masm) 41 #define __ ACCESS_MASM(masm)
41 42
42 void ToNumberStub::Generate(MacroAssembler* masm) { 43 void ToNumberStub::Generate(MacroAssembler* masm) {
43 // The ToNumber stub takes one argument in eax. 44 // The ToNumber stub takes one argument in eax.
44 NearLabel check_heap_number, call_builtin; 45 NearLabel check_heap_number, call_builtin;
45 __ test(eax, Immediate(kSmiTagMask)); 46 __ test(eax, Immediate(kSmiTagMask));
46 __ j(not_zero, &check_heap_number); 47 __ j(not_zero, &check_heap_number);
47 __ ret(0); 48 __ ret(0);
48 49
49 __ bind(&check_heap_number); 50 __ bind(&check_heap_number);
50 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 51 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
51 __ cmp(Operand(ebx), Immediate(Factory::heap_number_map())); 52 __ cmp(Operand(ebx), Immediate(FACTORY->heap_number_map()));
52 __ j(not_equal, &call_builtin); 53 __ j(not_equal, &call_builtin);
53 __ ret(0); 54 __ ret(0);
54 55
55 __ bind(&call_builtin); 56 __ bind(&call_builtin);
56 __ pop(ecx); // Pop return address. 57 __ pop(ecx); // Pop return address.
57 __ push(eax); 58 __ push(eax);
58 __ push(ecx); // Push return address. 59 __ push(ecx); // Push return address.
59 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); 60 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
60 } 61 }
61 62
(...skipping 13 matching lines...) Expand all
75 76
76 // Compute the function map in the current global context and set that 77 // Compute the function map in the current global context and set that
77 // as the map of the allocated object. 78 // as the map of the allocated object.
78 __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 79 __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
79 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); 80 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset));
80 __ mov(ecx, Operand(ecx, Context::SlotOffset(map_index))); 81 __ mov(ecx, Operand(ecx, Context::SlotOffset(map_index)));
81 __ mov(FieldOperand(eax, JSObject::kMapOffset), ecx); 82 __ mov(FieldOperand(eax, JSObject::kMapOffset), ecx);
82 83
83 // Initialize the rest of the function. We don't have to update the 84 // Initialize the rest of the function. We don't have to update the
84 // write barrier because the allocated object is in new space. 85 // write barrier because the allocated object is in new space.
85 __ mov(ebx, Immediate(Factory::empty_fixed_array())); 86 __ mov(ebx, Immediate(FACTORY->empty_fixed_array()));
86 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ebx); 87 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ebx);
87 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); 88 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx);
88 __ mov(FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset), 89 __ mov(FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset),
89 Immediate(Factory::the_hole_value())); 90 Immediate(FACTORY->the_hole_value()));
90 __ mov(FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset), edx); 91 __ mov(FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset), edx);
91 __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi); 92 __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi);
92 __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx); 93 __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx);
93 __ mov(FieldOperand(eax, JSFunction::kNextFunctionLinkOffset), 94 __ mov(FieldOperand(eax, JSFunction::kNextFunctionLinkOffset),
94 Immediate(Factory::undefined_value())); 95 Immediate(FACTORY->undefined_value()));
95 96
96 // Initialize the code pointer in the function to be the one 97 // Initialize the code pointer in the function to be the one
97 // found in the shared function info object. 98 // found in the shared function info object.
98 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); 99 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
99 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); 100 __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
100 __ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx); 101 __ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx);
101 102
102 // Return and remove the on-stack parameter. 103 // Return and remove the on-stack parameter.
103 __ ret(1 * kPointerSize); 104 __ ret(1 * kPointerSize);
104 105
105 // Create a new closure through the slower runtime call. 106 // Create a new closure through the slower runtime call.
106 __ bind(&gc); 107 __ bind(&gc);
107 __ pop(ecx); // Temporarily remove return address. 108 __ pop(ecx); // Temporarily remove return address.
108 __ pop(edx); 109 __ pop(edx);
109 __ push(esi); 110 __ push(esi);
110 __ push(edx); 111 __ push(edx);
111 __ push(Immediate(Factory::false_value())); 112 __ push(Immediate(FACTORY->false_value()));
112 __ push(ecx); // Restore return address. 113 __ push(ecx); // Restore return address.
113 __ TailCallRuntime(Runtime::kNewClosure, 3, 1); 114 __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
114 } 115 }
115 116
116 117
117 void FastNewContextStub::Generate(MacroAssembler* masm) { 118 void FastNewContextStub::Generate(MacroAssembler* masm) {
118 // Try to allocate the context in new space. 119 // Try to allocate the context in new space.
119 Label gc; 120 Label gc;
120 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 121 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
121 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, 122 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
122 eax, ebx, ecx, &gc, TAG_OBJECT); 123 eax, ebx, ecx, &gc, TAG_OBJECT);
123 124
124 // Get the function from the stack. 125 // Get the function from the stack.
125 __ mov(ecx, Operand(esp, 1 * kPointerSize)); 126 __ mov(ecx, Operand(esp, 1 * kPointerSize));
126 127
127 // Setup the object header. 128 // Setup the object header.
128 __ mov(FieldOperand(eax, HeapObject::kMapOffset), Factory::context_map()); 129 __ mov(FieldOperand(eax, HeapObject::kMapOffset), FACTORY->context_map());
129 __ mov(FieldOperand(eax, Context::kLengthOffset), 130 __ mov(FieldOperand(eax, Context::kLengthOffset),
130 Immediate(Smi::FromInt(length))); 131 Immediate(Smi::FromInt(length)));
131 132
132 // Setup the fixed slots. 133 // Setup the fixed slots.
133 __ Set(ebx, Immediate(0)); // Set to NULL. 134 __ Set(ebx, Immediate(0)); // Set to NULL.
134 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx); 135 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx);
135 __ mov(Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)), eax); 136 __ mov(Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)), eax);
136 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), ebx); 137 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), ebx);
137 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx); 138 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx);
138 139
139 // Copy the global object from the surrounding context. We go through the 140 // Copy the global object from the surrounding context. We go through the
140 // context in the function (ecx) to match the allocation behavior we have 141 // context in the function (ecx) to match the allocation behavior we have
141 // in the runtime system (see Heap::AllocateFunctionContext). 142 // in the runtime system (see Heap::AllocateFunctionContext).
142 __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset)); 143 __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset));
143 __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX))); 144 __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX)));
144 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); 145 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx);
145 146
146 // Initialize the rest of the slots to undefined. 147 // Initialize the rest of the slots to undefined.
147 __ mov(ebx, Factory::undefined_value()); 148 __ mov(ebx, FACTORY->undefined_value());
148 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { 149 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
149 __ mov(Operand(eax, Context::SlotOffset(i)), ebx); 150 __ mov(Operand(eax, Context::SlotOffset(i)), ebx);
150 } 151 }
151 152
152 // Return and remove the on-stack parameter. 153 // Return and remove the on-stack parameter.
153 __ mov(esi, Operand(eax)); 154 __ mov(esi, Operand(eax));
154 __ ret(1 * kPointerSize); 155 __ ret(1 * kPointerSize);
155 156
156 // Need to collect. Call into runtime system. 157 // Need to collect. Call into runtime system.
157 __ bind(&gc); 158 __ bind(&gc);
(...skipping 15 matching lines...) Expand all
173 // Load boilerplate object into ecx and check if we need to create a 174 // Load boilerplate object into ecx and check if we need to create a
174 // boilerplate. 175 // boilerplate.
175 Label slow_case; 176 Label slow_case;
176 __ mov(ecx, Operand(esp, 3 * kPointerSize)); 177 __ mov(ecx, Operand(esp, 3 * kPointerSize));
177 __ mov(eax, Operand(esp, 2 * kPointerSize)); 178 __ mov(eax, Operand(esp, 2 * kPointerSize));
178 STATIC_ASSERT(kPointerSize == 4); 179 STATIC_ASSERT(kPointerSize == 4);
179 STATIC_ASSERT(kSmiTagSize == 1); 180 STATIC_ASSERT(kSmiTagSize == 1);
180 STATIC_ASSERT(kSmiTag == 0); 181 STATIC_ASSERT(kSmiTag == 0);
181 __ mov(ecx, FieldOperand(ecx, eax, times_half_pointer_size, 182 __ mov(ecx, FieldOperand(ecx, eax, times_half_pointer_size,
182 FixedArray::kHeaderSize)); 183 FixedArray::kHeaderSize));
183 __ cmp(ecx, Factory::undefined_value()); 184 __ cmp(ecx, FACTORY->undefined_value());
184 __ j(equal, &slow_case); 185 __ j(equal, &slow_case);
185 186
186 if (FLAG_debug_code) { 187 if (FLAG_debug_code) {
187 const char* message; 188 const char* message;
188 Handle<Map> expected_map; 189 Handle<Map> expected_map;
189 if (mode_ == CLONE_ELEMENTS) { 190 if (mode_ == CLONE_ELEMENTS) {
190 message = "Expected (writable) fixed array"; 191 message = "Expected (writable) fixed array";
191 expected_map = Factory::fixed_array_map(); 192 expected_map = FACTORY->fixed_array_map();
192 } else { 193 } else {
193 ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS); 194 ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS);
194 message = "Expected copy-on-write fixed array"; 195 message = "Expected copy-on-write fixed array";
195 expected_map = Factory::fixed_cow_array_map(); 196 expected_map = FACTORY->fixed_cow_array_map();
196 } 197 }
197 __ push(ecx); 198 __ push(ecx);
198 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset)); 199 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset));
199 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), expected_map); 200 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), expected_map);
200 __ Assert(equal, message); 201 __ Assert(equal, message);
201 __ pop(ecx); 202 __ pop(ecx);
202 } 203 }
203 204
204 // Allocate both the JS array and the elements array in one big 205 // Allocate both the JS array and the elements array in one big
205 // allocation. This avoids multiple limit checks. 206 // allocation. This avoids multiple limit checks.
(...skipping 28 matching lines...) Expand all
234 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 235 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
235 } 236 }
236 237
237 238
238 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). 239 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
239 void ToBooleanStub::Generate(MacroAssembler* masm) { 240 void ToBooleanStub::Generate(MacroAssembler* masm) {
240 NearLabel false_result, true_result, not_string; 241 NearLabel false_result, true_result, not_string;
241 __ mov(eax, Operand(esp, 1 * kPointerSize)); 242 __ mov(eax, Operand(esp, 1 * kPointerSize));
242 243
243 // 'null' => false. 244 // 'null' => false.
244 __ cmp(eax, Factory::null_value()); 245 __ cmp(eax, FACTORY->null_value());
245 __ j(equal, &false_result); 246 __ j(equal, &false_result);
246 247
247 // Get the map and type of the heap object. 248 // Get the map and type of the heap object.
248 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 249 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
249 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); 250 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
250 251
251 // Undetectable => false. 252 // Undetectable => false.
252 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), 253 __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
253 1 << Map::kIsUndetectable); 254 1 << Map::kIsUndetectable);
254 __ j(not_zero, &false_result); 255 __ j(not_zero, &false_result);
255 256
256 // JavaScript object => true. 257 // JavaScript object => true.
257 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE); 258 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE);
258 __ j(above_equal, &true_result); 259 __ j(above_equal, &true_result);
259 260
260 // String value => false iff empty. 261 // String value => false iff empty.
261 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE); 262 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
262 __ j(above_equal, &not_string); 263 __ j(above_equal, &not_string);
263 STATIC_ASSERT(kSmiTag == 0); 264 STATIC_ASSERT(kSmiTag == 0);
264 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0)); 265 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0));
265 __ j(zero, &false_result); 266 __ j(zero, &false_result);
266 __ jmp(&true_result); 267 __ jmp(&true_result);
267 268
268 __ bind(&not_string); 269 __ bind(&not_string);
269 // HeapNumber => false iff +0, -0, or NaN. 270 // HeapNumber => false iff +0, -0, or NaN.
270 __ cmp(edx, Factory::heap_number_map()); 271 __ cmp(edx, FACTORY->heap_number_map());
271 __ j(not_equal, &true_result); 272 __ j(not_equal, &true_result);
272 __ fldz(); 273 __ fldz();
273 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 274 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
274 __ FCmp(); 275 __ FCmp();
275 __ j(zero, &false_result); 276 __ j(zero, &false_result);
276 // Fall through to |true_result|. 277 // Fall through to |true_result|.
277 278
278 // Return 1/0 for true/false in eax. 279 // Return 1/0 for true/false in eax.
279 __ bind(&true_result); 280 __ bind(&true_result);
280 __ mov(eax, 1); 281 __ mov(eax, 1);
(...skipping 12 matching lines...) Expand all
293 if (save_doubles_ == kSaveFPRegs) { 294 if (save_doubles_ == kSaveFPRegs) {
294 CpuFeatures::Scope scope(SSE2); 295 CpuFeatures::Scope scope(SSE2);
295 __ sub(Operand(esp), Immediate(kDoubleSize * XMMRegister::kNumRegisters)); 296 __ sub(Operand(esp), Immediate(kDoubleSize * XMMRegister::kNumRegisters));
296 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { 297 for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
297 XMMRegister reg = XMMRegister::from_code(i); 298 XMMRegister reg = XMMRegister::from_code(i);
298 __ movdbl(Operand(esp, i * kDoubleSize), reg); 299 __ movdbl(Operand(esp, i * kDoubleSize), reg);
299 } 300 }
300 } 301 }
301 const int argument_count = 0; 302 const int argument_count = 0;
302 __ PrepareCallCFunction(argument_count, ecx); 303 __ PrepareCallCFunction(argument_count, ecx);
303 ExternalReference store_buffer_overflow = 304 __ CallCFunction(ExternalReference::store_buffer_overflow_function(),
304 ExternalReference(Runtime::FunctionForId(Runtime::kStoreBufferOverflow)); 305 argument_count);
305 __ CallCFunction(store_buffer_overflow, argument_count);
306 if (save_doubles_ == kSaveFPRegs) { 306 if (save_doubles_ == kSaveFPRegs) {
307 CpuFeatures::Scope scope(SSE2); 307 CpuFeatures::Scope scope(SSE2);
308 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { 308 for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
309 XMMRegister reg = XMMRegister::from_code(i); 309 XMMRegister reg = XMMRegister::from_code(i);
310 __ movdbl(reg, Operand(esp, i * kDoubleSize)); 310 __ movdbl(reg, Operand(esp, i * kDoubleSize));
311 } 311 }
312 __ add(Operand(esp), Immediate(kDoubleSize * XMMRegister::kNumRegisters)); 312 __ add(Operand(esp), Immediate(kDoubleSize * XMMRegister::kNumRegisters));
313 } 313 }
314 __ popad(); 314 __ popad();
315 __ ret(0); 315 __ ret(0);
316 } 316 }
317 317
318 318
319 const char* GenericBinaryOpStub::GetName() { 319 const char* GenericBinaryOpStub::GetName() {
320 if (name_ != NULL) return name_; 320 if (name_ != NULL) return name_;
321 const int kMaxNameLength = 100; 321 const int kMaxNameLength = 100;
322 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength); 322 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
323 kMaxNameLength);
323 if (name_ == NULL) return "OOM"; 324 if (name_ == NULL) return "OOM";
324 const char* op_name = Token::Name(op_); 325 const char* op_name = Token::Name(op_);
325 const char* overwrite_name; 326 const char* overwrite_name;
326 switch (mode_) { 327 switch (mode_) {
327 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 328 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
328 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 329 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
329 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 330 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
330 default: overwrite_name = "UnknownOverwrite"; break; 331 default: overwrite_name = "UnknownOverwrite"; break;
331 } 332 }
332 333
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 387 }
387 } else { 388 } else {
388 // Order of moves is not important. 389 // Order of moves is not important.
389 __ mov(left_arg, left); 390 __ mov(left_arg, left);
390 __ mov(right_arg, right); 391 __ mov(right_arg, right);
391 } 392 }
392 } 393 }
393 394
394 // Update flags to indicate that arguments are in registers. 395 // Update flags to indicate that arguments are in registers.
395 SetArgsInRegisters(); 396 SetArgsInRegisters();
396 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); 397 __ IncrementCounter(COUNTERS->generic_binary_stub_calls_regs(), 1);
397 } 398 }
398 399
399 // Call the stub. 400 // Call the stub.
400 __ CallStub(this); 401 __ CallStub(this);
401 } 402 }
402 403
403 404
404 void GenericBinaryOpStub::GenerateCall( 405 void GenericBinaryOpStub::GenerateCall(
405 MacroAssembler* masm, 406 MacroAssembler* masm,
406 Register left, 407 Register left,
(...skipping 15 matching lines...) Expand all
422 // For non-commutative operations, left and right_arg might be 423 // For non-commutative operations, left and right_arg might be
423 // the same register. Therefore, the order of the moves is 424 // the same register. Therefore, the order of the moves is
424 // important here in order to not overwrite left before moving 425 // important here in order to not overwrite left before moving
425 // it to left_arg. 426 // it to left_arg.
426 __ mov(left_arg, left); 427 __ mov(left_arg, left);
427 __ mov(right_arg, Immediate(right)); 428 __ mov(right_arg, Immediate(right));
428 } 429 }
429 430
430 // Update flags to indicate that arguments are in registers. 431 // Update flags to indicate that arguments are in registers.
431 SetArgsInRegisters(); 432 SetArgsInRegisters();
432 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); 433 __ IncrementCounter(COUNTERS->generic_binary_stub_calls_regs(), 1);
433 } 434 }
434 435
435 // Call the stub. 436 // Call the stub.
436 __ CallStub(this); 437 __ CallStub(this);
437 } 438 }
438 439
439 440
440 void GenericBinaryOpStub::GenerateCall( 441 void GenericBinaryOpStub::GenerateCall(
441 MacroAssembler* masm, 442 MacroAssembler* masm,
442 Smi* left, 443 Smi* left,
(...skipping 14 matching lines...) Expand all
457 } else { 458 } else {
458 // For non-commutative operations, right and left_arg might be 459 // For non-commutative operations, right and left_arg might be
459 // the same register. Therefore, the order of the moves is 460 // the same register. Therefore, the order of the moves is
460 // important here in order to not overwrite right before moving 461 // important here in order to not overwrite right before moving
461 // it to right_arg. 462 // it to right_arg.
462 __ mov(right_arg, right); 463 __ mov(right_arg, right);
463 __ mov(left_arg, Immediate(left)); 464 __ mov(left_arg, Immediate(left));
464 } 465 }
465 // Update flags to indicate that arguments are in registers. 466 // Update flags to indicate that arguments are in registers.
466 SetArgsInRegisters(); 467 SetArgsInRegisters();
467 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); 468 __ IncrementCounter(COUNTERS->generic_binary_stub_calls_regs(), 1);
468 } 469 }
469 470
470 // Call the stub. 471 // Call the stub.
471 __ CallStub(this); 472 __ CallStub(this);
472 } 473 }
473 474
474 475
475 class FloatingPointHelper : public AllStatic { 476 class FloatingPointHelper : public AllStatic {
476 public: 477 public:
477 478
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 // overflowed the smi range). 786 // overflowed the smi range).
786 switch (op_) { 787 switch (op_) {
787 case Token::SHL: { 788 case Token::SHL: {
788 Comment perform_float(masm, "-- Perform float operation on smis"); 789 Comment perform_float(masm, "-- Perform float operation on smis");
789 __ bind(&use_fp_on_smis); 790 __ bind(&use_fp_on_smis);
790 if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) { 791 if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) {
791 // Result we want is in left == edx, so we can put the allocated heap 792 // Result we want is in left == edx, so we can put the allocated heap
792 // number in eax. 793 // number in eax.
793 __ AllocateHeapNumber(eax, ecx, ebx, slow); 794 __ AllocateHeapNumber(eax, ecx, ebx, slow);
794 // Store the result in the HeapNumber and return. 795 // Store the result in the HeapNumber and return.
795 if (CpuFeatures::IsSupported(SSE2)) { 796 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
796 CpuFeatures::Scope use_sse2(SSE2); 797 CpuFeatures::Scope use_sse2(SSE2);
797 __ cvtsi2sd(xmm0, Operand(left)); 798 __ cvtsi2sd(xmm0, Operand(left));
798 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 799 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
799 } else { 800 } else {
800 // It's OK to overwrite the right argument on the stack because we 801 // It's OK to overwrite the right argument on the stack because we
801 // are about to return. 802 // are about to return.
802 __ mov(Operand(esp, 1 * kPointerSize), left); 803 __ mov(Operand(esp, 1 * kPointerSize), left);
803 __ fild_s(Operand(esp, 1 * kPointerSize)); 804 __ fild_s(Operand(esp, 1 * kPointerSize));
804 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 805 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
805 } 806 }
(...skipping 29 matching lines...) Expand all
835 // Left was clobbered but a copy is in edi. Right is in ebx for 836 // Left was clobbered but a copy is in edi. Right is in ebx for
836 // division. 837 // division.
837 __ mov(edx, edi); 838 __ mov(edx, edi);
838 __ mov(eax, right); 839 __ mov(eax, right);
839 break; 840 break;
840 default: UNREACHABLE(); 841 default: UNREACHABLE();
841 break; 842 break;
842 } 843 }
843 if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) { 844 if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) {
844 __ AllocateHeapNumber(ecx, ebx, no_reg, slow); 845 __ AllocateHeapNumber(ecx, ebx, no_reg, slow);
845 if (CpuFeatures::IsSupported(SSE2)) { 846 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
846 CpuFeatures::Scope use_sse2(SSE2); 847 CpuFeatures::Scope use_sse2(SSE2);
847 FloatingPointHelper::LoadSSE2Smis(masm, ebx); 848 FloatingPointHelper::LoadSSE2Smis(masm, ebx);
848 switch (op_) { 849 switch (op_) {
849 case Token::ADD: __ addsd(xmm0, xmm1); break; 850 case Token::ADD: __ addsd(xmm0, xmm1); break;
850 case Token::SUB: __ subsd(xmm0, xmm1); break; 851 case Token::SUB: __ subsd(xmm0, xmm1); break;
851 case Token::MUL: __ mulsd(xmm0, xmm1); break; 852 case Token::MUL: __ mulsd(xmm0, xmm1); break;
852 case Token::DIV: __ divsd(xmm0, xmm1); break; 853 case Token::DIV: __ divsd(xmm0, xmm1); break;
853 default: UNREACHABLE(); 854 default: UNREACHABLE();
854 } 855 }
855 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); 856 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 901
901 default: 902 default:
902 break; 903 break;
903 } 904 }
904 } 905 }
905 906
906 907
907 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 908 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
908 Label call_runtime; 909 Label call_runtime;
909 910
910 __ IncrementCounter(&Counters::generic_binary_stub_calls, 1); 911 __ IncrementCounter(COUNTERS->generic_binary_stub_calls(), 1);
911 912
912 if (runtime_operands_type_ == BinaryOpIC::UNINIT_OR_SMI) { 913 if (runtime_operands_type_ == BinaryOpIC::UNINIT_OR_SMI) {
913 Label slow; 914 Label slow;
914 if (ShouldGenerateSmiCode()) GenerateSmiCode(masm, &slow); 915 if (ShouldGenerateSmiCode()) GenerateSmiCode(masm, &slow);
915 __ bind(&slow); 916 __ bind(&slow);
916 GenerateTypeTransition(masm); 917 GenerateTypeTransition(masm);
917 } 918 }
918 919
919 // Generate fast case smi code if requested. This flag is set when the fast 920 // Generate fast case smi code if requested. This flag is set when the fast
920 // case smi code is not generated by the caller. Generating it here will speed 921 // case smi code is not generated by the caller. Generating it here will speed
(...skipping 18 matching lines...) Expand all
939 // Execution reaches this point when the first non-smi argument occurs 940 // Execution reaches this point when the first non-smi argument occurs
940 // (and only if smi code is generated). This is the right moment to 941 // (and only if smi code is generated). This is the right moment to
941 // patch to HEAP_NUMBERS state. The transition is attempted only for 942 // patch to HEAP_NUMBERS state. The transition is attempted only for
942 // the four basic operations. The stub stays in the DEFAULT state 943 // the four basic operations. The stub stays in the DEFAULT state
943 // forever for all other operations (also if smi code is skipped). 944 // forever for all other operations (also if smi code is skipped).
944 GenerateTypeTransition(masm); 945 GenerateTypeTransition(masm);
945 break; 946 break;
946 } 947 }
947 948
948 Label not_floats; 949 Label not_floats;
949 if (CpuFeatures::IsSupported(SSE2)) { 950 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
950 CpuFeatures::Scope use_sse2(SSE2); 951 CpuFeatures::Scope use_sse2(SSE2);
951 if (static_operands_type_.IsNumber()) { 952 if (static_operands_type_.IsNumber()) {
952 if (FLAG_debug_code) { 953 if (FLAG_debug_code) {
953 // Assert at runtime that inputs are only numbers. 954 // Assert at runtime that inputs are only numbers.
954 __ AbortIfNotNumber(edx); 955 __ AbortIfNotNumber(edx);
955 __ AbortIfNotNumber(eax); 956 __ AbortIfNotNumber(eax);
956 } 957 }
957 if (static_operands_type_.IsSmi()) { 958 if (static_operands_type_.IsSmi()) {
958 if (FLAG_debug_code) { 959 if (FLAG_debug_code) {
959 __ AbortIfNotSmi(edx); 960 __ AbortIfNotSmi(edx);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 __ test(eax, Immediate(kSmiTagMask)); 1074 __ test(eax, Immediate(kSmiTagMask));
1074 __ j(not_zero, &skip_allocation, not_taken); 1075 __ j(not_zero, &skip_allocation, not_taken);
1075 // Fall through! 1076 // Fall through!
1076 case NO_OVERWRITE: 1077 case NO_OVERWRITE:
1077 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 1078 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
1078 __ bind(&skip_allocation); 1079 __ bind(&skip_allocation);
1079 break; 1080 break;
1080 default: UNREACHABLE(); 1081 default: UNREACHABLE();
1081 } 1082 }
1082 // Store the result in the HeapNumber and return. 1083 // Store the result in the HeapNumber and return.
1083 if (CpuFeatures::IsSupported(SSE2)) { 1084 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
1084 CpuFeatures::Scope use_sse2(SSE2); 1085 CpuFeatures::Scope use_sse2(SSE2);
1085 __ cvtsi2sd(xmm0, Operand(ebx)); 1086 __ cvtsi2sd(xmm0, Operand(ebx));
1086 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 1087 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
1087 } else { 1088 } else {
1088 __ mov(Operand(esp, 1 * kPointerSize), ebx); 1089 __ mov(Operand(esp, 1 * kPointerSize), ebx);
1089 __ fild_s(Operand(esp, 1 * kPointerSize)); 1090 __ fild_s(Operand(esp, 1 * kPointerSize));
1090 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 1091 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
1091 } 1092 }
1092 GenerateReturn(masm); 1093 GenerateReturn(masm);
1093 } 1094 }
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 break; 1386 break;
1386 default: 1387 default:
1387 UNREACHABLE(); 1388 UNREACHABLE();
1388 } 1389 }
1389 } 1390 }
1390 1391
1391 1392
1392 const char* TypeRecordingBinaryOpStub::GetName() { 1393 const char* TypeRecordingBinaryOpStub::GetName() {
1393 if (name_ != NULL) return name_; 1394 if (name_ != NULL) return name_;
1394 const int kMaxNameLength = 100; 1395 const int kMaxNameLength = 100;
1395 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength); 1396 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
1397 kMaxNameLength);
1396 if (name_ == NULL) return "OOM"; 1398 if (name_ == NULL) return "OOM";
1397 const char* op_name = Token::Name(op_); 1399 const char* op_name = Token::Name(op_);
1398 const char* overwrite_name; 1400 const char* overwrite_name;
1399 switch (mode_) { 1401 switch (mode_) {
1400 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 1402 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
1401 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 1403 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
1402 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 1404 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
1403 default: overwrite_name = "UnknownOverwrite"; break; 1405 default: overwrite_name = "UnknownOverwrite"; break;
1404 } 1406 }
1405 1407
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 } else { 1669 } else {
1668 ASSERT(allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS); 1670 ASSERT(allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS);
1669 switch (op_) { 1671 switch (op_) {
1670 case Token::SHL: { 1672 case Token::SHL: {
1671 Comment perform_float(masm, "-- Perform float operation on smis"); 1673 Comment perform_float(masm, "-- Perform float operation on smis");
1672 __ bind(&use_fp_on_smis); 1674 __ bind(&use_fp_on_smis);
1673 // Result we want is in left == edx, so we can put the allocated heap 1675 // Result we want is in left == edx, so we can put the allocated heap
1674 // number in eax. 1676 // number in eax.
1675 __ AllocateHeapNumber(eax, ecx, ebx, slow); 1677 __ AllocateHeapNumber(eax, ecx, ebx, slow);
1676 // Store the result in the HeapNumber and return. 1678 // Store the result in the HeapNumber and return.
1677 if (CpuFeatures::IsSupported(SSE2)) { 1679 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
1678 CpuFeatures::Scope use_sse2(SSE2); 1680 CpuFeatures::Scope use_sse2(SSE2);
1679 __ cvtsi2sd(xmm0, Operand(left)); 1681 __ cvtsi2sd(xmm0, Operand(left));
1680 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 1682 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
1681 } else { 1683 } else {
1682 // It's OK to overwrite the right argument on the stack because we 1684 // It's OK to overwrite the right argument on the stack because we
1683 // are about to return. 1685 // are about to return.
1684 __ mov(Operand(esp, 1 * kPointerSize), left); 1686 __ mov(Operand(esp, 1 * kPointerSize), left);
1685 __ fild_s(Operand(esp, 1 * kPointerSize)); 1687 __ fild_s(Operand(esp, 1 * kPointerSize));
1686 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 1688 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
1687 } 1689 }
(...skipping 24 matching lines...) Expand all
1712 case Token::DIV: 1714 case Token::DIV:
1713 // Left was clobbered but a copy is in edi. Right is in ebx for 1715 // Left was clobbered but a copy is in edi. Right is in ebx for
1714 // division. 1716 // division.
1715 __ mov(edx, edi); 1717 __ mov(edx, edi);
1716 __ mov(eax, right); 1718 __ mov(eax, right);
1717 break; 1719 break;
1718 default: UNREACHABLE(); 1720 default: UNREACHABLE();
1719 break; 1721 break;
1720 } 1722 }
1721 __ AllocateHeapNumber(ecx, ebx, no_reg, slow); 1723 __ AllocateHeapNumber(ecx, ebx, no_reg, slow);
1722 if (CpuFeatures::IsSupported(SSE2)) { 1724 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
1723 CpuFeatures::Scope use_sse2(SSE2); 1725 CpuFeatures::Scope use_sse2(SSE2);
1724 FloatingPointHelper::LoadSSE2Smis(masm, ebx); 1726 FloatingPointHelper::LoadSSE2Smis(masm, ebx);
1725 switch (op_) { 1727 switch (op_) {
1726 case Token::ADD: __ addsd(xmm0, xmm1); break; 1728 case Token::ADD: __ addsd(xmm0, xmm1); break;
1727 case Token::SUB: __ subsd(xmm0, xmm1); break; 1729 case Token::SUB: __ subsd(xmm0, xmm1); break;
1728 case Token::MUL: __ mulsd(xmm0, xmm1); break; 1730 case Token::MUL: __ mulsd(xmm0, xmm1); break;
1729 case Token::DIV: __ divsd(xmm0, xmm1); break; 1731 case Token::DIV: __ divsd(xmm0, xmm1); break;
1730 default: UNREACHABLE(); 1732 default: UNREACHABLE();
1731 } 1733 }
1732 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); 1734 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 ASSERT(operands_type_ == TRBinaryOpIC::INT32); 1846 ASSERT(operands_type_ == TRBinaryOpIC::INT32);
1845 1847
1846 // Floating point case. 1848 // Floating point case.
1847 switch (op_) { 1849 switch (op_) {
1848 case Token::ADD: 1850 case Token::ADD:
1849 case Token::SUB: 1851 case Token::SUB:
1850 case Token::MUL: 1852 case Token::MUL:
1851 case Token::DIV: { 1853 case Token::DIV: {
1852 Label not_floats; 1854 Label not_floats;
1853 Label not_int32; 1855 Label not_int32;
1854 if (CpuFeatures::IsSupported(SSE2)) { 1856 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
1855 CpuFeatures::Scope use_sse2(SSE2); 1857 CpuFeatures::Scope use_sse2(SSE2);
1856 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats); 1858 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
1857 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, &not_int32, ecx); 1859 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, &not_int32, ecx);
1858 switch (op_) { 1860 switch (op_) {
1859 case Token::ADD: __ addsd(xmm0, xmm1); break; 1861 case Token::ADD: __ addsd(xmm0, xmm1); break;
1860 case Token::SUB: __ subsd(xmm0, xmm1); break; 1862 case Token::SUB: __ subsd(xmm0, xmm1); break;
1861 case Token::MUL: __ mulsd(xmm0, xmm1); break; 1863 case Token::MUL: __ mulsd(xmm0, xmm1); break;
1862 case Token::DIV: __ divsd(xmm0, xmm1); break; 1864 case Token::DIV: __ divsd(xmm0, xmm1); break;
1863 default: UNREACHABLE(); 1865 default: UNREACHABLE();
1864 } 1866 }
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1965 __ test(eax, Immediate(kSmiTagMask)); 1967 __ test(eax, Immediate(kSmiTagMask));
1966 __ j(not_zero, &skip_allocation, not_taken); 1968 __ j(not_zero, &skip_allocation, not_taken);
1967 // Fall through! 1969 // Fall through!
1968 case NO_OVERWRITE: 1970 case NO_OVERWRITE:
1969 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 1971 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
1970 __ bind(&skip_allocation); 1972 __ bind(&skip_allocation);
1971 break; 1973 break;
1972 default: UNREACHABLE(); 1974 default: UNREACHABLE();
1973 } 1975 }
1974 // Store the result in the HeapNumber and return. 1976 // Store the result in the HeapNumber and return.
1975 if (CpuFeatures::IsSupported(SSE2)) { 1977 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
1976 CpuFeatures::Scope use_sse2(SSE2); 1978 CpuFeatures::Scope use_sse2(SSE2);
1977 __ cvtsi2sd(xmm0, Operand(ebx)); 1979 __ cvtsi2sd(xmm0, Operand(ebx));
1978 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 1980 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
1979 } else { 1981 } else {
1980 __ mov(Operand(esp, 1 * kPointerSize), ebx); 1982 __ mov(Operand(esp, 1 * kPointerSize), ebx);
1981 __ fild_s(Operand(esp, 1 * kPointerSize)); 1983 __ fild_s(Operand(esp, 1 * kPointerSize));
1982 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 1984 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
1983 } 1985 }
1984 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. 1986 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack.
1985 } 1987 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2045 Label call_runtime; 2047 Label call_runtime;
2046 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); 2048 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER);
2047 2049
2048 // Floating point case. 2050 // Floating point case.
2049 switch (op_) { 2051 switch (op_) {
2050 case Token::ADD: 2052 case Token::ADD:
2051 case Token::SUB: 2053 case Token::SUB:
2052 case Token::MUL: 2054 case Token::MUL:
2053 case Token::DIV: { 2055 case Token::DIV: {
2054 Label not_floats; 2056 Label not_floats;
2055 if (CpuFeatures::IsSupported(SSE2)) { 2057 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
2056 CpuFeatures::Scope use_sse2(SSE2); 2058 CpuFeatures::Scope use_sse2(SSE2);
2057 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats); 2059 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
2058 2060
2059 switch (op_) { 2061 switch (op_) {
2060 case Token::ADD: __ addsd(xmm0, xmm1); break; 2062 case Token::ADD: __ addsd(xmm0, xmm1); break;
2061 case Token::SUB: __ subsd(xmm0, xmm1); break; 2063 case Token::SUB: __ subsd(xmm0, xmm1); break;
2062 case Token::MUL: __ mulsd(xmm0, xmm1); break; 2064 case Token::MUL: __ mulsd(xmm0, xmm1); break;
2063 case Token::DIV: __ divsd(xmm0, xmm1); break; 2065 case Token::DIV: __ divsd(xmm0, xmm1); break;
2064 default: UNREACHABLE(); 2066 default: UNREACHABLE();
2065 } 2067 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2148 __ test(eax, Immediate(kSmiTagMask)); 2150 __ test(eax, Immediate(kSmiTagMask));
2149 __ j(not_zero, &skip_allocation, not_taken); 2151 __ j(not_zero, &skip_allocation, not_taken);
2150 // Fall through! 2152 // Fall through!
2151 case NO_OVERWRITE: 2153 case NO_OVERWRITE:
2152 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 2154 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
2153 __ bind(&skip_allocation); 2155 __ bind(&skip_allocation);
2154 break; 2156 break;
2155 default: UNREACHABLE(); 2157 default: UNREACHABLE();
2156 } 2158 }
2157 // Store the result in the HeapNumber and return. 2159 // Store the result in the HeapNumber and return.
2158 if (CpuFeatures::IsSupported(SSE2)) { 2160 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
2159 CpuFeatures::Scope use_sse2(SSE2); 2161 CpuFeatures::Scope use_sse2(SSE2);
2160 __ cvtsi2sd(xmm0, Operand(ebx)); 2162 __ cvtsi2sd(xmm0, Operand(ebx));
2161 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 2163 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
2162 } else { 2164 } else {
2163 __ mov(Operand(esp, 1 * kPointerSize), ebx); 2165 __ mov(Operand(esp, 1 * kPointerSize), ebx);
2164 __ fild_s(Operand(esp, 1 * kPointerSize)); 2166 __ fild_s(Operand(esp, 1 * kPointerSize));
2165 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 2167 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
2166 } 2168 }
2167 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. 2169 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack.
2168 } 2170 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2219 break; 2221 break;
2220 default: 2222 default:
2221 UNREACHABLE(); 2223 UNREACHABLE();
2222 } 2224 }
2223 } 2225 }
2224 2226
2225 2227
2226 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { 2228 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
2227 Label call_runtime; 2229 Label call_runtime;
2228 2230
2229 __ IncrementCounter(&Counters::generic_binary_stub_calls, 1); 2231 __ IncrementCounter(COUNTERS->generic_binary_stub_calls(), 1);
2230 2232
2231 switch (op_) { 2233 switch (op_) {
2232 case Token::ADD: 2234 case Token::ADD:
2233 case Token::SUB: 2235 case Token::SUB:
2234 case Token::MUL: 2236 case Token::MUL:
2235 case Token::DIV: 2237 case Token::DIV:
2236 break; 2238 break;
2237 case Token::MOD: 2239 case Token::MOD:
2238 case Token::BIT_OR: 2240 case Token::BIT_OR:
2239 case Token::BIT_AND: 2241 case Token::BIT_AND:
2240 case Token::BIT_XOR: 2242 case Token::BIT_XOR:
2241 case Token::SAR: 2243 case Token::SAR:
2242 case Token::SHL: 2244 case Token::SHL:
2243 case Token::SHR: 2245 case Token::SHR:
2244 GenerateRegisterArgsPush(masm); 2246 GenerateRegisterArgsPush(masm);
2245 break; 2247 break;
2246 default: 2248 default:
2247 UNREACHABLE(); 2249 UNREACHABLE();
2248 } 2250 }
2249 2251
2250 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); 2252 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
2251 2253
2252 // Floating point case. 2254 // Floating point case.
2253 switch (op_) { 2255 switch (op_) {
2254 case Token::ADD: 2256 case Token::ADD:
2255 case Token::SUB: 2257 case Token::SUB:
2256 case Token::MUL: 2258 case Token::MUL:
2257 case Token::DIV: { 2259 case Token::DIV: {
2258 Label not_floats; 2260 Label not_floats;
2259 if (CpuFeatures::IsSupported(SSE2)) { 2261 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
2260 CpuFeatures::Scope use_sse2(SSE2); 2262 CpuFeatures::Scope use_sse2(SSE2);
2261 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats); 2263 FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
2262 2264
2263 switch (op_) { 2265 switch (op_) {
2264 case Token::ADD: __ addsd(xmm0, xmm1); break; 2266 case Token::ADD: __ addsd(xmm0, xmm1); break;
2265 case Token::SUB: __ subsd(xmm0, xmm1); break; 2267 case Token::SUB: __ subsd(xmm0, xmm1); break;
2266 case Token::MUL: __ mulsd(xmm0, xmm1); break; 2268 case Token::MUL: __ mulsd(xmm0, xmm1); break;
2267 case Token::DIV: __ divsd(xmm0, xmm1); break; 2269 case Token::DIV: __ divsd(xmm0, xmm1); break;
2268 default: UNREACHABLE(); 2270 default: UNREACHABLE();
2269 } 2271 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2347 __ test(eax, Immediate(kSmiTagMask)); 2349 __ test(eax, Immediate(kSmiTagMask));
2348 __ j(not_zero, &skip_allocation, not_taken); 2350 __ j(not_zero, &skip_allocation, not_taken);
2349 // Fall through! 2351 // Fall through!
2350 case NO_OVERWRITE: 2352 case NO_OVERWRITE:
2351 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 2353 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
2352 __ bind(&skip_allocation); 2354 __ bind(&skip_allocation);
2353 break; 2355 break;
2354 default: UNREACHABLE(); 2356 default: UNREACHABLE();
2355 } 2357 }
2356 // Store the result in the HeapNumber and return. 2358 // Store the result in the HeapNumber and return.
2357 if (CpuFeatures::IsSupported(SSE2)) { 2359 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
2358 CpuFeatures::Scope use_sse2(SSE2); 2360 CpuFeatures::Scope use_sse2(SSE2);
2359 __ cvtsi2sd(xmm0, Operand(ebx)); 2361 __ cvtsi2sd(xmm0, Operand(ebx));
2360 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 2362 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
2361 } else { 2363 } else {
2362 __ mov(Operand(esp, 1 * kPointerSize), ebx); 2364 __ mov(Operand(esp, 1 * kPointerSize), ebx);
2363 __ fild_s(Operand(esp, 1 * kPointerSize)); 2365 __ fild_s(Operand(esp, 1 * kPointerSize));
2364 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 2366 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
2365 } 2367 }
2366 __ ret(2 * kPointerSize); 2368 __ ret(2 * kPointerSize);
2367 } 2369 }
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
2535 __ sub(Operand(esp), Immediate(2 * kPointerSize)); 2537 __ sub(Operand(esp), Immediate(2 * kPointerSize));
2536 __ mov(Operand(esp, 0), eax); 2538 __ mov(Operand(esp, 0), eax);
2537 __ fild_s(Operand(esp, 0)); 2539 __ fild_s(Operand(esp, 0));
2538 __ fst_d(Operand(esp, 0)); 2540 __ fst_d(Operand(esp, 0));
2539 __ pop(edx); 2541 __ pop(edx);
2540 __ pop(ebx); 2542 __ pop(ebx);
2541 __ jmp(&loaded); 2543 __ jmp(&loaded);
2542 __ bind(&input_not_smi); 2544 __ bind(&input_not_smi);
2543 // Check if input is a HeapNumber. 2545 // Check if input is a HeapNumber.
2544 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2546 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2545 __ cmp(Operand(ebx), Immediate(Factory::heap_number_map())); 2547 __ cmp(Operand(ebx), Immediate(FACTORY->heap_number_map()));
2546 __ j(not_equal, &runtime_call); 2548 __ j(not_equal, &runtime_call);
2547 // Input is a HeapNumber. Push it on the FPU stack and load its 2549 // Input is a HeapNumber. Push it on the FPU stack and load its
2548 // low and high words into ebx, edx. 2550 // low and high words into ebx, edx.
2549 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 2551 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
2550 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); 2552 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
2551 __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset)); 2553 __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
2552 2554
2553 __ bind(&loaded); 2555 __ bind(&loaded);
2554 } else { // UNTAGGED. 2556 } else { // UNTAGGED.
2555 if (CpuFeatures::IsSupported(SSE4_1)) { 2557 if (Isolate::Current()->cpu_features()->IsSupported(SSE4_1)) {
2556 CpuFeatures::Scope sse4_scope(SSE4_1); 2558 CpuFeatures::Scope sse4_scope(SSE4_1);
2557 __ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx. 2559 __ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx.
2558 } else { 2560 } else {
2559 __ pshufd(xmm0, xmm1, 0x1); 2561 __ pshufd(xmm0, xmm1, 0x1);
2560 __ movd(Operand(edx), xmm0); 2562 __ movd(Operand(edx), xmm0);
2561 } 2563 }
2562 __ movd(Operand(ebx), xmm1); 2564 __ movd(Operand(ebx), xmm1);
2563 } 2565 }
2564 2566
2565 // ST[0] or xmm1 == double value 2567 // ST[0] or xmm1 == double value
2566 // ebx = low 32 bits of double value 2568 // ebx = low 32 bits of double value
2567 // edx = high 32 bits of double value 2569 // edx = high 32 bits of double value
2568 // Compute hash (the shifts are arithmetic): 2570 // Compute hash (the shifts are arithmetic):
2569 // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1); 2571 // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
2570 __ mov(ecx, ebx); 2572 __ mov(ecx, ebx);
2571 __ xor_(ecx, Operand(edx)); 2573 __ xor_(ecx, Operand(edx));
2572 __ mov(eax, ecx); 2574 __ mov(eax, ecx);
2573 __ sar(eax, 16); 2575 __ sar(eax, 16);
2574 __ xor_(ecx, Operand(eax)); 2576 __ xor_(ecx, Operand(eax));
2575 __ mov(eax, ecx); 2577 __ mov(eax, ecx);
2576 __ sar(eax, 8); 2578 __ sar(eax, 8);
2577 __ xor_(ecx, Operand(eax)); 2579 __ xor_(ecx, Operand(eax));
2578 ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize)); 2580 ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
2579 __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1)); 2581 __ and_(Operand(ecx),
2582 Immediate(TranscendentalCache::SubCache::kCacheSize - 1));
2580 2583
2581 // ST[0] or xmm1 == double value. 2584 // ST[0] or xmm1 == double value.
2582 // ebx = low 32 bits of double value. 2585 // ebx = low 32 bits of double value.
2583 // edx = high 32 bits of double value. 2586 // edx = high 32 bits of double value.
2584 // ecx = TranscendentalCache::hash(double value). 2587 // ecx = TranscendentalCache::hash(double value).
2585 __ mov(eax, 2588 __ mov(eax,
2586 Immediate(ExternalReference::transcendental_cache_array_address())); 2589 Immediate(ExternalReference::transcendental_cache_array_address()));
2587 // Eax points to cache array. 2590 // Eax points to cache array.
2588 __ mov(eax, Operand(eax, type_ * sizeof(TranscendentalCache::caches_[0]))); 2591 __ mov(eax, Operand(eax, type_ * sizeof(
2592 Isolate::Current()->transcendental_cache()->caches_[0])));
2589 // Eax points to the cache for the type type_. 2593 // Eax points to the cache for the type type_.
2590 // If NULL, the cache hasn't been initialized yet, so go through runtime. 2594 // If NULL, the cache hasn't been initialized yet, so go through runtime.
2591 __ test(eax, Operand(eax)); 2595 __ test(eax, Operand(eax));
2592 __ j(zero, &runtime_call_clear_stack); 2596 __ j(zero, &runtime_call_clear_stack);
2593 #ifdef DEBUG 2597 #ifdef DEBUG
2594 // Check that the layout of cache elements match expectations. 2598 // Check that the layout of cache elements match expectations.
2595 { TranscendentalCache::Element test_elem[2]; 2599 { TranscendentalCache::SubCache::Element test_elem[2];
2596 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); 2600 char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
2597 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); 2601 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
2598 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); 2602 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
2599 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); 2603 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
2600 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); 2604 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
2601 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. 2605 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
2602 CHECK_EQ(0, elem_in0 - elem_start); 2606 CHECK_EQ(0, elem_in0 - elem_start);
2603 CHECK_EQ(kIntSize, elem_in1 - elem_start); 2607 CHECK_EQ(kIntSize, elem_in1 - elem_start);
2604 CHECK_EQ(2 * kIntSize, elem_out - elem_start); 2608 CHECK_EQ(2 * kIntSize, elem_out - elem_start);
2605 } 2609 }
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
2794 // trashed registers. 2798 // trashed registers.
2795 void IntegerConvert(MacroAssembler* masm, 2799 void IntegerConvert(MacroAssembler* masm,
2796 Register source, 2800 Register source,
2797 TypeInfo type_info, 2801 TypeInfo type_info,
2798 bool use_sse3, 2802 bool use_sse3,
2799 Label* conversion_failure) { 2803 Label* conversion_failure) {
2800 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); 2804 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx));
2801 Label done, right_exponent, normal_exponent; 2805 Label done, right_exponent, normal_exponent;
2802 Register scratch = ebx; 2806 Register scratch = ebx;
2803 Register scratch2 = edi; 2807 Register scratch2 = edi;
2804 if (type_info.IsInteger32() && CpuFeatures::IsEnabled(SSE2)) { 2808 if (type_info.IsInteger32() &&
2809 Isolate::Current()->cpu_features()->IsEnabled(SSE2)) {
2805 CpuFeatures::Scope scope(SSE2); 2810 CpuFeatures::Scope scope(SSE2);
2806 __ cvttsd2si(ecx, FieldOperand(source, HeapNumber::kValueOffset)); 2811 __ cvttsd2si(ecx, FieldOperand(source, HeapNumber::kValueOffset));
2807 return; 2812 return;
2808 } 2813 }
2809 if (!type_info.IsInteger32() || !use_sse3) { 2814 if (!type_info.IsInteger32() || !use_sse3) {
2810 // Get exponent word. 2815 // Get exponent word.
2811 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); 2816 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset));
2812 // Get exponent alone in scratch2. 2817 // Get exponent alone in scratch2.
2813 __ mov(scratch2, scratch); 2818 __ mov(scratch2, scratch);
2814 __ and_(scratch2, HeapNumber::kExponentMask); 2819 __ and_(scratch2, HeapNumber::kExponentMask);
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 3002
2998 // Test if arg1 is a Smi. 3003 // Test if arg1 is a Smi.
2999 __ test(edx, Immediate(kSmiTagMask)); 3004 __ test(edx, Immediate(kSmiTagMask));
3000 __ j(not_zero, &arg1_is_object); 3005 __ j(not_zero, &arg1_is_object);
3001 3006
3002 __ SmiUntag(edx); 3007 __ SmiUntag(edx);
3003 __ jmp(&load_arg2); 3008 __ jmp(&load_arg2);
3004 3009
3005 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 3010 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
3006 __ bind(&check_undefined_arg1); 3011 __ bind(&check_undefined_arg1);
3007 __ cmp(edx, Factory::undefined_value()); 3012 __ cmp(edx, FACTORY->undefined_value());
3008 __ j(not_equal, conversion_failure); 3013 __ j(not_equal, conversion_failure);
3009 __ mov(edx, Immediate(0)); 3014 __ mov(edx, Immediate(0));
3010 __ jmp(&load_arg2); 3015 __ jmp(&load_arg2);
3011 3016
3012 __ bind(&arg1_is_object); 3017 __ bind(&arg1_is_object);
3013 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 3018 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
3014 __ cmp(ebx, Factory::heap_number_map()); 3019 __ cmp(ebx, FACTORY->heap_number_map());
3015 __ j(not_equal, &check_undefined_arg1); 3020 __ j(not_equal, &check_undefined_arg1);
3016 3021
3017 // Get the untagged integer version of the edx heap number in ecx. 3022 // Get the untagged integer version of the edx heap number in ecx.
3018 IntegerConvert(masm, 3023 IntegerConvert(masm,
3019 edx, 3024 edx,
3020 TypeInfo::Unknown(), 3025 TypeInfo::Unknown(),
3021 use_sse3, 3026 use_sse3,
3022 conversion_failure); 3027 conversion_failure);
3023 __ mov(edx, ecx); 3028 __ mov(edx, ecx);
3024 3029
3025 // Here edx has the untagged integer, eax has a Smi or a heap number. 3030 // Here edx has the untagged integer, eax has a Smi or a heap number.
3026 __ bind(&load_arg2); 3031 __ bind(&load_arg2);
3027 3032
3028 // Test if arg2 is a Smi. 3033 // Test if arg2 is a Smi.
3029 __ test(eax, Immediate(kSmiTagMask)); 3034 __ test(eax, Immediate(kSmiTagMask));
3030 __ j(not_zero, &arg2_is_object); 3035 __ j(not_zero, &arg2_is_object);
3031 3036
3032 __ SmiUntag(eax); 3037 __ SmiUntag(eax);
3033 __ mov(ecx, eax); 3038 __ mov(ecx, eax);
3034 __ jmp(&done); 3039 __ jmp(&done);
3035 3040
3036 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 3041 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
3037 __ bind(&check_undefined_arg2); 3042 __ bind(&check_undefined_arg2);
3038 __ cmp(eax, Factory::undefined_value()); 3043 __ cmp(eax, FACTORY->undefined_value());
3039 __ j(not_equal, conversion_failure); 3044 __ j(not_equal, conversion_failure);
3040 __ mov(ecx, Immediate(0)); 3045 __ mov(ecx, Immediate(0));
3041 __ jmp(&done); 3046 __ jmp(&done);
3042 3047
3043 __ bind(&arg2_is_object); 3048 __ bind(&arg2_is_object);
3044 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 3049 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
3045 __ cmp(ebx, Factory::heap_number_map()); 3050 __ cmp(ebx, FACTORY->heap_number_map());
3046 __ j(not_equal, &check_undefined_arg2); 3051 __ j(not_equal, &check_undefined_arg2);
3047 3052
3048 // Get the untagged integer version of the eax heap number in ecx. 3053 // Get the untagged integer version of the eax heap number in ecx.
3049 IntegerConvert(masm, 3054 IntegerConvert(masm,
3050 eax, 3055 eax,
3051 TypeInfo::Unknown(), 3056 TypeInfo::Unknown(),
3052 use_sse3, 3057 use_sse3,
3053 conversion_failure); 3058 conversion_failure);
3054 __ bind(&done); 3059 __ bind(&done);
3055 __ mov(eax, edx); 3060 __ mov(eax, edx);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
3122 __ bind(&done); 3127 __ bind(&done);
3123 } 3128 }
3124 3129
3125 3130
3126 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, 3131 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm,
3127 Label* not_numbers) { 3132 Label* not_numbers) {
3128 NearLabel load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; 3133 NearLabel load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
3129 // Load operand in edx into xmm0, or branch to not_numbers. 3134 // Load operand in edx into xmm0, or branch to not_numbers.
3130 __ test(edx, Immediate(kSmiTagMask)); 3135 __ test(edx, Immediate(kSmiTagMask));
3131 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. 3136 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi.
3132 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map()); 3137 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), FACTORY->heap_number_map());
3133 __ j(not_equal, not_numbers); // Argument in edx is not a number. 3138 __ j(not_equal, not_numbers); // Argument in edx is not a number.
3134 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 3139 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
3135 __ bind(&load_eax); 3140 __ bind(&load_eax);
3136 // Load operand in eax into xmm1, or branch to not_numbers. 3141 // Load operand in eax into xmm1, or branch to not_numbers.
3137 __ test(eax, Immediate(kSmiTagMask)); 3142 __ test(eax, Immediate(kSmiTagMask));
3138 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. 3143 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi.
3139 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map()); 3144 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), FACTORY->heap_number_map());
3140 __ j(equal, &load_float_eax); 3145 __ j(equal, &load_float_eax);
3141 __ jmp(not_numbers); // Argument in eax is not a number. 3146 __ jmp(not_numbers); // Argument in eax is not a number.
3142 __ bind(&load_smi_edx); 3147 __ bind(&load_smi_edx);
3143 __ SmiUntag(edx); // Untag smi before converting to float. 3148 __ SmiUntag(edx); // Untag smi before converting to float.
3144 __ cvtsi2sd(xmm0, Operand(edx)); 3149 __ cvtsi2sd(xmm0, Operand(edx));
3145 __ SmiTag(edx); // Retag smi for heap number overwriting test. 3150 __ SmiTag(edx); // Retag smi for heap number overwriting test.
3146 __ jmp(&load_eax); 3151 __ jmp(&load_eax);
3147 __ bind(&load_smi_eax); 3152 __ bind(&load_smi_eax);
3148 __ SmiUntag(eax); // Untag smi before converting to float. 3153 __ SmiUntag(eax); // Untag smi before converting to float.
3149 __ cvtsi2sd(xmm1, Operand(eax)); 3154 __ cvtsi2sd(xmm1, Operand(eax));
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
3247 3252
3248 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, 3253 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
3249 Label* non_float, 3254 Label* non_float,
3250 Register scratch) { 3255 Register scratch) {
3251 NearLabel test_other, done; 3256 NearLabel test_other, done;
3252 // Test if both operands are floats or smi -> scratch=k_is_float; 3257 // Test if both operands are floats or smi -> scratch=k_is_float;
3253 // Otherwise scratch = k_not_float. 3258 // Otherwise scratch = k_not_float.
3254 __ test(edx, Immediate(kSmiTagMask)); 3259 __ test(edx, Immediate(kSmiTagMask));
3255 __ j(zero, &test_other, not_taken); // argument in edx is OK 3260 __ j(zero, &test_other, not_taken); // argument in edx is OK
3256 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); 3261 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset));
3257 __ cmp(scratch, Factory::heap_number_map()); 3262 __ cmp(scratch, FACTORY->heap_number_map());
3258 __ j(not_equal, non_float); // argument in edx is not a number -> NaN 3263 __ j(not_equal, non_float); // argument in edx is not a number -> NaN
3259 3264
3260 __ bind(&test_other); 3265 __ bind(&test_other);
3261 __ test(eax, Immediate(kSmiTagMask)); 3266 __ test(eax, Immediate(kSmiTagMask));
3262 __ j(zero, &done); // argument in eax is OK 3267 __ j(zero, &done); // argument in eax is OK
3263 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); 3268 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset));
3264 __ cmp(scratch, Factory::heap_number_map()); 3269 __ cmp(scratch, FACTORY->heap_number_map());
3265 __ j(not_equal, non_float); // argument in eax is not a number -> NaN 3270 __ j(not_equal, non_float); // argument in eax is not a number -> NaN
3266 3271
3267 // Fall-through: Both operands are numbers. 3272 // Fall-through: Both operands are numbers.
3268 __ bind(&done); 3273 __ bind(&done);
3269 } 3274 }
3270 3275
3271 3276
3272 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, 3277 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm,
3273 Label* non_int32) { 3278 Label* non_int32) {
3274 return; 3279 return;
(...skipping 25 matching lines...) Expand all
3300 __ j(overflow, &undo, not_taken); 3305 __ j(overflow, &undo, not_taken);
3301 __ StubReturn(1); 3306 __ StubReturn(1);
3302 3307
3303 // Try floating point case. 3308 // Try floating point case.
3304 __ bind(&try_float); 3309 __ bind(&try_float);
3305 } else if (FLAG_debug_code) { 3310 } else if (FLAG_debug_code) {
3306 __ AbortIfSmi(eax); 3311 __ AbortIfSmi(eax);
3307 } 3312 }
3308 3313
3309 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 3314 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
3310 __ cmp(edx, Factory::heap_number_map()); 3315 __ cmp(edx, FACTORY->heap_number_map());
3311 __ j(not_equal, &slow); 3316 __ j(not_equal, &slow);
3312 if (overwrite_ == UNARY_OVERWRITE) { 3317 if (overwrite_ == UNARY_OVERWRITE) {
3313 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); 3318 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
3314 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. 3319 __ xor_(edx, HeapNumber::kSignMask); // Flip sign.
3315 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); 3320 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx);
3316 } else { 3321 } else {
3317 __ mov(edx, Operand(eax)); 3322 __ mov(edx, Operand(eax));
3318 // edx: operand 3323 // edx: operand
3319 __ AllocateHeapNumber(eax, ebx, ecx, &undo); 3324 __ AllocateHeapNumber(eax, ebx, ecx, &undo);
3320 // eax: allocated 'empty' number 3325 // eax: allocated 'empty' number
(...skipping 11 matching lines...) Expand all
3332 __ not_(eax); 3337 __ not_(eax);
3333 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag. 3338 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag.
3334 __ ret(0); 3339 __ ret(0);
3335 __ bind(&non_smi); 3340 __ bind(&non_smi);
3336 } else if (FLAG_debug_code) { 3341 } else if (FLAG_debug_code) {
3337 __ AbortIfSmi(eax); 3342 __ AbortIfSmi(eax);
3338 } 3343 }
3339 3344
3340 // Check if the operand is a heap number. 3345 // Check if the operand is a heap number.
3341 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 3346 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
3342 __ cmp(edx, Factory::heap_number_map()); 3347 __ cmp(edx, FACTORY->heap_number_map());
3343 __ j(not_equal, &slow, not_taken); 3348 __ j(not_equal, &slow, not_taken);
3344 3349
3345 // Convert the heap number in eax to an untagged integer in ecx. 3350 // Convert the heap number in eax to an untagged integer in ecx.
3346 IntegerConvert(masm, 3351 IntegerConvert(masm,
3347 eax, 3352 eax,
3348 TypeInfo::Unknown(), 3353 TypeInfo::Unknown(),
3349 CpuFeatures::IsSupported(SSE3), 3354 Isolate::Current()->cpu_features()->IsSupported(SSE3),
3350 &slow); 3355 &slow);
3351 3356
3352 // Do the bitwise operation and check if the result fits in a smi. 3357 // Do the bitwise operation and check if the result fits in a smi.
3353 NearLabel try_float; 3358 NearLabel try_float;
3354 __ not_(ecx); 3359 __ not_(ecx);
3355 __ cmp(ecx, 0xc0000000); 3360 __ cmp(ecx, 0xc0000000);
3356 __ j(sign, &try_float, not_taken); 3361 __ j(sign, &try_float, not_taken);
3357 3362
3358 // Tag the result as a smi and we're done. 3363 // Tag the result as a smi and we're done.
3359 STATIC_ASSERT(kSmiTagSize == 1); 3364 STATIC_ASSERT(kSmiTagSize == 1);
3360 __ lea(eax, Operand(ecx, times_2, kSmiTag)); 3365 __ lea(eax, Operand(ecx, times_2, kSmiTag));
3361 __ jmp(&done); 3366 __ jmp(&done);
3362 3367
3363 // Try to store the result in a heap number. 3368 // Try to store the result in a heap number.
3364 __ bind(&try_float); 3369 __ bind(&try_float);
3365 if (overwrite_ == UNARY_NO_OVERWRITE) { 3370 if (overwrite_ == UNARY_NO_OVERWRITE) {
3366 // Allocate a fresh heap number, but don't overwrite eax until 3371 // Allocate a fresh heap number, but don't overwrite eax until
3367 // we're sure we can do it without going through the slow case 3372 // we're sure we can do it without going through the slow case
3368 // that needs the value in eax. 3373 // that needs the value in eax.
3369 __ AllocateHeapNumber(ebx, edx, edi, &slow); 3374 __ AllocateHeapNumber(ebx, edx, edi, &slow);
3370 __ mov(eax, Operand(ebx)); 3375 __ mov(eax, Operand(ebx));
3371 } 3376 }
3372 if (CpuFeatures::IsSupported(SSE2)) { 3377 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
3373 CpuFeatures::Scope use_sse2(SSE2); 3378 CpuFeatures::Scope use_sse2(SSE2);
3374 __ cvtsi2sd(xmm0, Operand(ecx)); 3379 __ cvtsi2sd(xmm0, Operand(ecx));
3375 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 3380 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
3376 } else { 3381 } else {
3377 __ push(ecx); 3382 __ push(ecx);
3378 __ fild_s(Operand(esp, 0)); 3383 __ fild_s(Operand(esp, 0));
3379 __ pop(ecx); 3384 __ pop(ecx);
3380 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3385 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
3381 } 3386 }
3382 } else { 3387 } else {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3435 __ j(not_zero, &base_nonsmi); 3440 __ j(not_zero, &base_nonsmi);
3436 3441
3437 // Optimized version when both exponent and base are smis. 3442 // Optimized version when both exponent and base are smis.
3438 Label powi; 3443 Label powi;
3439 __ SmiUntag(edx); 3444 __ SmiUntag(edx);
3440 __ cvtsi2sd(xmm0, Operand(edx)); 3445 __ cvtsi2sd(xmm0, Operand(edx));
3441 __ jmp(&powi); 3446 __ jmp(&powi);
3442 // exponent is smi and base is a heapnumber. 3447 // exponent is smi and base is a heapnumber.
3443 __ bind(&base_nonsmi); 3448 __ bind(&base_nonsmi);
3444 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 3449 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3445 Factory::heap_number_map()); 3450 FACTORY->heap_number_map());
3446 __ j(not_equal, &call_runtime); 3451 __ j(not_equal, &call_runtime);
3447 3452
3448 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 3453 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
3449 3454
3450 // Optimized version of pow if exponent is a smi. 3455 // Optimized version of pow if exponent is a smi.
3451 // xmm0 contains the base. 3456 // xmm0 contains the base.
3452 __ bind(&powi); 3457 __ bind(&powi);
3453 __ SmiUntag(eax); 3458 __ SmiUntag(eax);
3454 3459
3455 // Save exponent in base as we need to check if exponent is negative later. 3460 // 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
3487 __ ucomisd(xmm0, xmm1); 3492 __ ucomisd(xmm0, xmm1);
3488 __ j(equal, &call_runtime); 3493 __ j(equal, &call_runtime);
3489 __ divsd(xmm3, xmm1); 3494 __ divsd(xmm3, xmm1);
3490 __ movsd(xmm1, xmm3); 3495 __ movsd(xmm1, xmm3);
3491 __ jmp(&allocate_return); 3496 __ jmp(&allocate_return);
3492 3497
3493 // exponent (or both) is a heapnumber - no matter what we should now work 3498 // exponent (or both) is a heapnumber - no matter what we should now work
3494 // on doubles. 3499 // on doubles.
3495 __ bind(&exponent_nonsmi); 3500 __ bind(&exponent_nonsmi);
3496 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3501 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3497 Factory::heap_number_map()); 3502 FACTORY->heap_number_map());
3498 __ j(not_equal, &call_runtime); 3503 __ j(not_equal, &call_runtime);
3499 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); 3504 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
3500 // Test if exponent is nan. 3505 // Test if exponent is nan.
3501 __ ucomisd(xmm1, xmm1); 3506 __ ucomisd(xmm1, xmm1);
3502 __ j(parity_even, &call_runtime); 3507 __ j(parity_even, &call_runtime);
3503 3508
3504 NearLabel base_not_smi; 3509 NearLabel base_not_smi;
3505 NearLabel handle_special_cases; 3510 NearLabel handle_special_cases;
3506 __ test(edx, Immediate(kSmiTagMask)); 3511 __ test(edx, Immediate(kSmiTagMask));
3507 __ j(not_zero, &base_not_smi); 3512 __ j(not_zero, &base_not_smi);
3508 __ SmiUntag(edx); 3513 __ SmiUntag(edx);
3509 __ cvtsi2sd(xmm0, Operand(edx)); 3514 __ cvtsi2sd(xmm0, Operand(edx));
3510 __ jmp(&handle_special_cases); 3515 __ jmp(&handle_special_cases);
3511 3516
3512 __ bind(&base_not_smi); 3517 __ bind(&base_not_smi);
3513 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 3518 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3514 Factory::heap_number_map()); 3519 FACTORY->heap_number_map());
3515 __ j(not_equal, &call_runtime); 3520 __ j(not_equal, &call_runtime);
3516 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); 3521 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset));
3517 __ and_(ecx, HeapNumber::kExponentMask); 3522 __ and_(ecx, HeapNumber::kExponentMask);
3518 __ cmp(Operand(ecx), Immediate(HeapNumber::kExponentMask)); 3523 __ cmp(Operand(ecx), Immediate(HeapNumber::kExponentMask));
3519 // base is NaN or +/-Infinity 3524 // base is NaN or +/-Infinity
3520 __ j(greater_equal, &call_runtime); 3525 __ j(greater_equal, &call_runtime);
3521 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 3526 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
3522 3527
3523 // base is in xmm0 and exponent is in xmm1. 3528 // base is in xmm0 and exponent is in xmm1.
3524 __ bind(&handle_special_cases); 3529 __ bind(&handle_special_cases);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
3702 __ j(zero, &done); 3707 __ j(zero, &done);
3703 3708
3704 // Get the parameters pointer from the stack. 3709 // Get the parameters pointer from the stack.
3705 __ mov(edx, Operand(esp, 2 * kPointerSize)); 3710 __ mov(edx, Operand(esp, 2 * kPointerSize));
3706 3711
3707 // Setup the elements pointer in the allocated arguments object and 3712 // Setup the elements pointer in the allocated arguments object and
3708 // initialize the header in the elements fixed array. 3713 // initialize the header in the elements fixed array.
3709 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); 3714 __ lea(edi, Operand(eax, GetArgumentsObjectSize()));
3710 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); 3715 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
3711 __ mov(FieldOperand(edi, FixedArray::kMapOffset), 3716 __ mov(FieldOperand(edi, FixedArray::kMapOffset),
3712 Immediate(Factory::fixed_array_map())); 3717 Immediate(FACTORY->fixed_array_map()));
3713 3718
3714 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); 3719 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
3715 // Untag the length for the loop below. 3720 // Untag the length for the loop below.
3716 __ SmiUntag(ecx); 3721 __ SmiUntag(ecx);
3717 3722
3718 // Copy the fixed array slots. 3723 // Copy the fixed array slots.
3719 NearLabel loop; 3724 NearLabel loop;
3720 __ bind(&loop); 3725 __ bind(&loop);
3721 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. 3726 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver.
3722 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); 3727 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
3830 // edx: Number of capture registers 3835 // edx: Number of capture registers
3831 // Check that the fourth object is a JSArray object. 3836 // Check that the fourth object is a JSArray object.
3832 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); 3837 __ mov(eax, Operand(esp, kLastMatchInfoOffset));
3833 __ test(eax, Immediate(kSmiTagMask)); 3838 __ test(eax, Immediate(kSmiTagMask));
3834 __ j(zero, &runtime); 3839 __ j(zero, &runtime);
3835 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 3840 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
3836 __ j(not_equal, &runtime); 3841 __ j(not_equal, &runtime);
3837 // Check that the JSArray is in fast case. 3842 // Check that the JSArray is in fast case.
3838 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); 3843 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset));
3839 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); 3844 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset));
3840 __ cmp(eax, Factory::fixed_array_map()); 3845 __ cmp(eax, FACTORY->fixed_array_map());
3841 __ j(not_equal, &runtime); 3846 __ j(not_equal, &runtime);
3842 // Check that the last match info has space for the capture registers and the 3847 // Check that the last match info has space for the capture registers and the
3843 // additional information. 3848 // additional information.
3844 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); 3849 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset));
3845 __ SmiUntag(eax); 3850 __ SmiUntag(eax);
3846 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead)); 3851 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead));
3847 __ cmp(edx, Operand(eax)); 3852 __ cmp(edx, Operand(eax));
3848 __ j(greater, &runtime); 3853 __ j(greater, &runtime);
3849 3854
3850 // ecx: RegExp data (FixedArray) 3855 // ecx: RegExp data (FixedArray)
(...skipping 17 matching lines...) Expand all
3868 // string. In that case the subject string is just the first part of the cons 3873 // string. In that case the subject string is just the first part of the cons
3869 // string. Also in this case the first part of the cons string is known to be 3874 // string. Also in this case the first part of the cons string is known to be
3870 // a sequential string or an external string. 3875 // a sequential string or an external string.
3871 STATIC_ASSERT(kExternalStringTag != 0); 3876 STATIC_ASSERT(kExternalStringTag != 0);
3872 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); 3877 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0);
3873 __ test(Operand(ebx), 3878 __ test(Operand(ebx),
3874 Immediate(kIsNotStringMask | kExternalStringTag)); 3879 Immediate(kIsNotStringMask | kExternalStringTag));
3875 __ j(not_zero, &runtime); 3880 __ j(not_zero, &runtime);
3876 // String is a cons string. 3881 // String is a cons string.
3877 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); 3882 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset));
3878 __ cmp(Operand(edx), Factory::empty_string()); 3883 __ cmp(Operand(edx), FACTORY->empty_string());
3879 __ j(not_equal, &runtime); 3884 __ j(not_equal, &runtime);
3880 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); 3885 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
3881 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 3886 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
3882 // String is a cons string with empty second part. 3887 // String is a cons string with empty second part.
3883 // eax: first part of cons string. 3888 // eax: first part of cons string.
3884 // ebx: map of first part of cons string. 3889 // ebx: map of first part of cons string.
3885 // Is first part a flat two byte string? 3890 // Is first part a flat two byte string?
3886 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), 3891 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
3887 kStringRepresentationMask | kStringEncodingMask); 3892 kStringRepresentationMask | kStringEncodingMask);
3888 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); 3893 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
(...skipping 29 matching lines...) Expand all
3918 // Load used arguments before starting to push arguments for call to native 3923 // Load used arguments before starting to push arguments for call to native
3919 // RegExp code to avoid handling changing stack height. 3924 // RegExp code to avoid handling changing stack height.
3920 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); 3925 __ mov(ebx, Operand(esp, kPreviousIndexOffset));
3921 __ SmiUntag(ebx); // Previous index from smi. 3926 __ SmiUntag(ebx); // Previous index from smi.
3922 3927
3923 // eax: subject string 3928 // eax: subject string
3924 // ebx: previous index 3929 // ebx: previous index
3925 // edx: code 3930 // edx: code
3926 // edi: encoding of subject string (1 if ascii 0 if two_byte); 3931 // edi: encoding of subject string (1 if ascii 0 if two_byte);
3927 // All checks done. Now push arguments for native regexp code. 3932 // All checks done. Now push arguments for native regexp code.
3928 __ IncrementCounter(&Counters::regexp_entry_native, 1); 3933 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1);
3929 3934
3930 static const int kRegExpExecuteArguments = 7; 3935 // Isolates: note we add an additional parameter here (isolate pointer).
3936 static const int kRegExpExecuteArguments = 8;
3931 __ EnterApiExitFrame(kRegExpExecuteArguments); 3937 __ EnterApiExitFrame(kRegExpExecuteArguments);
3932 3938
3939 // Argument 8: Pass current isolate address.
3940 __ mov(Operand(esp, 7 * kPointerSize),
3941 Immediate(ExternalReference::isolate_address()));
3942
3933 // Argument 7: Indicate that this is a direct call from JavaScript. 3943 // Argument 7: Indicate that this is a direct call from JavaScript.
3934 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); 3944 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1));
3935 3945
3936 // Argument 6: Start (high end) of backtracking stack memory area. 3946 // Argument 6: Start (high end) of backtracking stack memory area.
3937 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); 3947 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address));
3938 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); 3948 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
3939 __ mov(Operand(esp, 5 * kPointerSize), ecx); 3949 __ mov(Operand(esp, 5 * kPointerSize), ecx);
3940 3950
3941 // Argument 5: static offsets vector buffer. 3951 // Argument 5: static offsets vector buffer.
3942 __ mov(Operand(esp, 4 * kPointerSize), 3952 __ mov(Operand(esp, 4 * kPointerSize),
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3985 Label failure; 3995 Label failure;
3986 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); 3996 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE);
3987 __ j(equal, &failure, taken); 3997 __ j(equal, &failure, taken);
3988 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); 3998 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION);
3989 // If not exception it can only be retry. Handle that in the runtime system. 3999 // If not exception it can only be retry. Handle that in the runtime system.
3990 __ j(not_equal, &runtime); 4000 __ j(not_equal, &runtime);
3991 // Result must now be exception. If there is no pending exception already a 4001 // Result must now be exception. If there is no pending exception already a
3992 // stack overflow (on the backtrack stack) was detected in RegExp code but 4002 // stack overflow (on the backtrack stack) was detected in RegExp code but
3993 // haven't created the exception yet. Handle that in the runtime system. 4003 // haven't created the exception yet. Handle that in the runtime system.
3994 // TODO(592): Rerunning the RegExp to get the stack overflow exception. 4004 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
3995 ExternalReference pending_exception(Top::k_pending_exception_address); 4005 ExternalReference pending_exception(Isolate::k_pending_exception_address);
3996 __ mov(edx, 4006 __ mov(edx,
3997 Operand::StaticVariable(ExternalReference::the_hole_value_location())); 4007 Operand::StaticVariable(ExternalReference::the_hole_value_location()));
3998 __ mov(eax, Operand::StaticVariable(pending_exception)); 4008 __ mov(eax, Operand::StaticVariable(pending_exception));
3999 __ cmp(edx, Operand(eax)); 4009 __ cmp(edx, Operand(eax));
4000 __ j(equal, &runtime); 4010 __ j(equal, &runtime);
4001 // For exception, throw the exception again. 4011 // For exception, throw the exception again.
4002 4012
4003 // Clear the pending exception variable. 4013 // Clear the pending exception variable.
4004 __ mov(Operand::StaticVariable(pending_exception), edx); 4014 __ mov(Operand::StaticVariable(pending_exception), edx);
4005 4015
4006 // Special handling of termination exceptions which are uncatchable 4016 // Special handling of termination exceptions which are uncatchable
4007 // by javascript code. 4017 // by javascript code.
4008 __ cmp(eax, Factory::termination_exception()); 4018 __ cmp(eax, FACTORY->termination_exception());
4009 Label throw_termination_exception; 4019 Label throw_termination_exception;
4010 __ j(equal, &throw_termination_exception); 4020 __ j(equal, &throw_termination_exception);
4011 4021
4012 // Handle normal exception by following handler chain. 4022 // Handle normal exception by following handler chain.
4013 __ Throw(eax); 4023 __ Throw(eax);
4014 4024
4015 __ bind(&throw_termination_exception); 4025 __ bind(&throw_termination_exception);
4016 __ ThrowUncatchable(TERMINATION, eax); 4026 __ ThrowUncatchable(TERMINATION, eax);
4017 4027
4018 __ bind(&failure); 4028 __ bind(&failure);
4019 // For failure to match, return null. 4029 // For failure to match, return null.
4020 __ mov(Operand(eax), Factory::null_value()); 4030 __ mov(Operand(eax), FACTORY->null_value());
4021 __ ret(4 * kPointerSize); 4031 __ ret(4 * kPointerSize);
4022 4032
4023 // Load RegExp data. 4033 // Load RegExp data.
4024 __ bind(&success); 4034 __ bind(&success);
4025 __ mov(eax, Operand(esp, kJSRegExpOffset)); 4035 __ mov(eax, Operand(esp, kJSRegExpOffset));
4026 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); 4036 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
4027 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); 4037 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
4028 // Calculate number of capture registers (number_of_captures + 1) * 2. 4038 // Calculate number of capture registers (number_of_captures + 1) * 2.
4029 STATIC_ASSERT(kSmiTag == 0); 4039 STATIC_ASSERT(kSmiTag == 0);
4030 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 4040 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
4115 edx, // Scratch register 4125 edx, // Scratch register
4116 &slowcase, 4126 &slowcase,
4117 TAG_OBJECT); 4127 TAG_OBJECT);
4118 // eax: Start of allocated area, object-tagged. 4128 // eax: Start of allocated area, object-tagged.
4119 4129
4120 // Set JSArray map to global.regexp_result_map(). 4130 // Set JSArray map to global.regexp_result_map().
4121 // Set empty properties FixedArray. 4131 // Set empty properties FixedArray.
4122 // Set elements to point to FixedArray allocated right after the JSArray. 4132 // Set elements to point to FixedArray allocated right after the JSArray.
4123 // Interleave operations for better latency. 4133 // Interleave operations for better latency.
4124 __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX)); 4134 __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX));
4125 __ mov(ecx, Immediate(Factory::empty_fixed_array())); 4135 __ mov(ecx, Immediate(FACTORY->empty_fixed_array()));
4126 __ lea(ebx, Operand(eax, JSRegExpResult::kSize)); 4136 __ lea(ebx, Operand(eax, JSRegExpResult::kSize));
4127 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset)); 4137 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset));
4128 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); 4138 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx);
4129 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); 4139 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx);
4130 __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX)); 4140 __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX));
4131 __ mov(FieldOperand(eax, HeapObject::kMapOffset), edx); 4141 __ mov(FieldOperand(eax, HeapObject::kMapOffset), edx);
4132 4142
4133 // Set input, index and length fields from arguments. 4143 // Set input, index and length fields from arguments.
4134 __ mov(ecx, Operand(esp, kPointerSize * 1)); 4144 __ mov(ecx, Operand(esp, kPointerSize * 1));
4135 __ mov(FieldOperand(eax, JSRegExpResult::kInputOffset), ecx); 4145 __ mov(FieldOperand(eax, JSRegExpResult::kInputOffset), ecx);
4136 __ mov(ecx, Operand(esp, kPointerSize * 2)); 4146 __ mov(ecx, Operand(esp, kPointerSize * 2));
4137 __ mov(FieldOperand(eax, JSRegExpResult::kIndexOffset), ecx); 4147 __ mov(FieldOperand(eax, JSRegExpResult::kIndexOffset), ecx);
4138 __ mov(ecx, Operand(esp, kPointerSize * 3)); 4148 __ mov(ecx, Operand(esp, kPointerSize * 3));
4139 __ mov(FieldOperand(eax, JSArray::kLengthOffset), ecx); 4149 __ mov(FieldOperand(eax, JSArray::kLengthOffset), ecx);
4140 4150
4141 // Fill out the elements FixedArray. 4151 // Fill out the elements FixedArray.
4142 // eax: JSArray. 4152 // eax: JSArray.
4143 // ebx: FixedArray. 4153 // ebx: FixedArray.
4144 // ecx: Number of elements in array, as smi. 4154 // ecx: Number of elements in array, as smi.
4145 4155
4146 // Set map. 4156 // Set map.
4147 __ mov(FieldOperand(ebx, HeapObject::kMapOffset), 4157 __ mov(FieldOperand(ebx, HeapObject::kMapOffset),
4148 Immediate(Factory::fixed_array_map())); 4158 Immediate(FACTORY->fixed_array_map()));
4149 // Set length. 4159 // Set length.
4150 __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx); 4160 __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx);
4151 // Fill contents of fixed-array with the-hole. 4161 // Fill contents of fixed-array with the-hole.
4152 __ SmiUntag(ecx); 4162 __ SmiUntag(ecx);
4153 __ mov(edx, Immediate(Factory::the_hole_value())); 4163 __ mov(edx, Immediate(FACTORY->the_hole_value()));
4154 __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize)); 4164 __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize));
4155 // Fill fixed array elements with hole. 4165 // Fill fixed array elements with hole.
4156 // eax: JSArray. 4166 // eax: JSArray.
4157 // ecx: Number of elements to fill. 4167 // ecx: Number of elements to fill.
4158 // ebx: Start of elements in FixedArray. 4168 // ebx: Start of elements in FixedArray.
4159 // edx: the hole. 4169 // edx: the hole.
4160 Label loop; 4170 Label loop;
4161 __ test(ecx, Operand(ecx)); 4171 __ test(ecx, Operand(ecx));
4162 __ bind(&loop); 4172 __ bind(&loop);
4163 __ j(less_equal, &done); // Jump if ecx is negative or zero. 4173 __ j(less_equal, &done); // Jump if ecx is negative or zero.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4208 } else { 4218 } else {
4209 NearLabel not_smi, hash_calculated; 4219 NearLabel not_smi, hash_calculated;
4210 STATIC_ASSERT(kSmiTag == 0); 4220 STATIC_ASSERT(kSmiTag == 0);
4211 __ test(object, Immediate(kSmiTagMask)); 4221 __ test(object, Immediate(kSmiTagMask));
4212 __ j(not_zero, &not_smi); 4222 __ j(not_zero, &not_smi);
4213 __ mov(scratch, object); 4223 __ mov(scratch, object);
4214 __ SmiUntag(scratch); 4224 __ SmiUntag(scratch);
4215 __ jmp(&smi_hash_calculated); 4225 __ jmp(&smi_hash_calculated);
4216 __ bind(&not_smi); 4226 __ bind(&not_smi);
4217 __ cmp(FieldOperand(object, HeapObject::kMapOffset), 4227 __ cmp(FieldOperand(object, HeapObject::kMapOffset),
4218 Factory::heap_number_map()); 4228 FACTORY->heap_number_map());
4219 __ j(not_equal, not_found); 4229 __ j(not_equal, not_found);
4220 STATIC_ASSERT(8 == kDoubleSize); 4230 STATIC_ASSERT(8 == kDoubleSize);
4221 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); 4231 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
4222 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); 4232 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
4223 // Object is heap number and hash is now in scratch. Calculate cache index. 4233 // Object is heap number and hash is now in scratch. Calculate cache index.
4224 __ and_(scratch, Operand(mask)); 4234 __ and_(scratch, Operand(mask));
4225 Register index = scratch; 4235 Register index = scratch;
4226 Register probe = mask; 4236 Register probe = mask;
4227 __ mov(probe, 4237 __ mov(probe,
4228 FieldOperand(number_string_cache, 4238 FieldOperand(number_string_cache,
4229 index, 4239 index,
4230 times_twice_pointer_size, 4240 times_twice_pointer_size,
4231 FixedArray::kHeaderSize)); 4241 FixedArray::kHeaderSize));
4232 __ test(probe, Immediate(kSmiTagMask)); 4242 __ test(probe, Immediate(kSmiTagMask));
4233 __ j(zero, not_found); 4243 __ j(zero, not_found);
4234 if (CpuFeatures::IsSupported(SSE2)) { 4244 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
4235 CpuFeatures::Scope fscope(SSE2); 4245 CpuFeatures::Scope fscope(SSE2);
4236 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); 4246 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
4237 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); 4247 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
4238 __ ucomisd(xmm0, xmm1); 4248 __ ucomisd(xmm0, xmm1);
4239 } else { 4249 } else {
4240 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); 4250 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset));
4241 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); 4251 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset));
4242 __ FCmp(); 4252 __ FCmp();
4243 } 4253 }
4244 __ j(parity_even, not_found); // Bail out if NaN is involved. 4254 __ j(parity_even, not_found); // Bail out if NaN is involved.
(...skipping 13 matching lines...) Expand all
4258 FixedArray::kHeaderSize)); 4268 FixedArray::kHeaderSize));
4259 __ j(not_equal, not_found); 4269 __ j(not_equal, not_found);
4260 4270
4261 // Get the result from the cache. 4271 // Get the result from the cache.
4262 __ bind(&load_result_from_cache); 4272 __ bind(&load_result_from_cache);
4263 __ mov(result, 4273 __ mov(result,
4264 FieldOperand(number_string_cache, 4274 FieldOperand(number_string_cache,
4265 index, 4275 index,
4266 times_twice_pointer_size, 4276 times_twice_pointer_size,
4267 FixedArray::kHeaderSize + kPointerSize)); 4277 FixedArray::kHeaderSize + kPointerSize));
4268 __ IncrementCounter(&Counters::number_to_string_native, 1); 4278 __ IncrementCounter(COUNTERS->number_to_string_native(), 1);
4269 } 4279 }
4270 4280
4271 4281
4272 void NumberToStringStub::Generate(MacroAssembler* masm) { 4282 void NumberToStringStub::Generate(MacroAssembler* masm) {
4273 Label runtime; 4283 Label runtime;
4274 4284
4275 __ mov(ebx, Operand(esp, kPointerSize)); 4285 __ mov(ebx, Operand(esp, kPointerSize));
4276 4286
4277 // Generate code to lookup number in the number string cache. 4287 // Generate code to lookup number in the number string cache.
4278 GenerateLookupNumberStringCache(masm, ebx, eax, ecx, edx, false, &runtime); 4288 GenerateLookupNumberStringCache(masm, ebx, eax, ecx, edx, false, &runtime);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
4324 // for NaN and undefined. 4334 // for NaN and undefined.
4325 { 4335 {
4326 Label not_identical; 4336 Label not_identical;
4327 __ cmp(eax, Operand(edx)); 4337 __ cmp(eax, Operand(edx));
4328 __ j(not_equal, &not_identical); 4338 __ j(not_equal, &not_identical);
4329 4339
4330 if (cc_ != equal) { 4340 if (cc_ != equal) {
4331 // Check for undefined. undefined OP undefined is false even though 4341 // Check for undefined. undefined OP undefined is false even though
4332 // undefined == undefined. 4342 // undefined == undefined.
4333 NearLabel check_for_nan; 4343 NearLabel check_for_nan;
4334 __ cmp(edx, Factory::undefined_value()); 4344 __ cmp(edx, FACTORY->undefined_value());
4335 __ j(not_equal, &check_for_nan); 4345 __ j(not_equal, &check_for_nan);
4336 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); 4346 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_))));
4337 __ ret(0); 4347 __ ret(0);
4338 __ bind(&check_for_nan); 4348 __ bind(&check_for_nan);
4339 } 4349 }
4340 4350
4341 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 4351 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
4342 // so we do the second best thing - test it ourselves. 4352 // so we do the second best thing - test it ourselves.
4343 // Note: if cc_ != equal, never_nan_nan_ is not used. 4353 // Note: if cc_ != equal, never_nan_nan_ is not used.
4344 if (never_nan_nan_ && (cc_ == equal)) { 4354 if (never_nan_nan_ && (cc_ == equal)) {
4345 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 4355 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
4346 __ ret(0); 4356 __ ret(0);
4347 } else { 4357 } else {
4348 NearLabel heap_number; 4358 NearLabel heap_number;
4349 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 4359 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
4350 Immediate(Factory::heap_number_map())); 4360 Immediate(FACTORY->heap_number_map()));
4351 __ j(equal, &heap_number); 4361 __ j(equal, &heap_number);
4352 if (cc_ != equal) { 4362 if (cc_ != equal) {
4353 // Call runtime on identical JSObjects. Otherwise return equal. 4363 // Call runtime on identical JSObjects. Otherwise return equal.
4354 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 4364 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
4355 __ j(above_equal, &not_identical); 4365 __ j(above_equal, &not_identical);
4356 } 4366 }
4357 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 4367 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
4358 __ ret(0); 4368 __ ret(0);
4359 4369
4360 __ bind(&heap_number); 4370 __ bind(&heap_number);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
4417 // ecx still holds eax & kSmiTag, which is either zero or one. 4427 // ecx still holds eax & kSmiTag, which is either zero or one.
4418 __ sub(Operand(ecx), Immediate(0x01)); 4428 __ sub(Operand(ecx), Immediate(0x01));
4419 __ mov(ebx, edx); 4429 __ mov(ebx, edx);
4420 __ xor_(ebx, Operand(eax)); 4430 __ xor_(ebx, Operand(eax));
4421 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. 4431 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx.
4422 __ xor_(ebx, Operand(eax)); 4432 __ xor_(ebx, Operand(eax));
4423 // if eax was smi, ebx is now edx, else eax. 4433 // if eax was smi, ebx is now edx, else eax.
4424 4434
4425 // Check if the non-smi operand is a heap number. 4435 // Check if the non-smi operand is a heap number.
4426 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 4436 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
4427 Immediate(Factory::heap_number_map())); 4437 Immediate(FACTORY->heap_number_map()));
4428 // If heap number, handle it in the slow case. 4438 // If heap number, handle it in the slow case.
4429 __ j(equal, &slow); 4439 __ j(equal, &slow);
4430 // Return non-equal (ebx is not zero) 4440 // Return non-equal (ebx is not zero)
4431 __ mov(eax, ebx); 4441 __ mov(eax, ebx);
4432 __ ret(0); 4442 __ ret(0);
4433 4443
4434 __ bind(&not_smis); 4444 __ bind(&not_smis);
4435 // If either operand is a JSObject or an oddball value, then they are not 4445 // If either operand is a JSObject or an oddball value, then they are not
4436 // equal since their pointers are different 4446 // equal since their pointers are different
4437 // There is no test for undetectability in strict equality. 4447 // There is no test for undetectability in strict equality.
(...skipping 24 matching lines...) Expand all
4462 __ j(equal, &return_not_equal); 4472 __ j(equal, &return_not_equal);
4463 4473
4464 // Fall through to the general case. 4474 // Fall through to the general case.
4465 __ bind(&slow); 4475 __ bind(&slow);
4466 } 4476 }
4467 4477
4468 // Generate the number comparison code. 4478 // Generate the number comparison code.
4469 if (include_number_compare_) { 4479 if (include_number_compare_) {
4470 Label non_number_comparison; 4480 Label non_number_comparison;
4471 Label unordered; 4481 Label unordered;
4472 if (CpuFeatures::IsSupported(SSE2)) { 4482 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
4473 CpuFeatures::Scope use_sse2(SSE2); 4483 CpuFeatures::Scope use_sse2(SSE2);
4474 CpuFeatures::Scope use_cmov(CMOV); 4484 CpuFeatures::Scope use_cmov(CMOV);
4475 4485
4476 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); 4486 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison);
4477 __ ucomisd(xmm0, xmm1); 4487 __ ucomisd(xmm0, xmm1);
4478 4488
4479 // Don't base result on EFLAGS when a NaN is involved. 4489 // Don't base result on EFLAGS when a NaN is involved.
4480 __ j(parity_even, &unordered, not_taken); 4490 __ j(parity_even, &unordered, not_taken);
4481 // Return a result of -1, 0, or 1, based on EFLAGS. 4491 // Return a result of -1, 0, or 1, based on EFLAGS.
4482 __ mov(eax, 0); // equal 4492 __ mov(eax, 0); // equal
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
4681 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 4691 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
4682 4692
4683 // Slow-case: Non-function called. 4693 // Slow-case: Non-function called.
4684 __ bind(&slow); 4694 __ bind(&slow);
4685 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 4695 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
4686 // of the original receiver from the call site). 4696 // of the original receiver from the call site).
4687 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); 4697 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi);
4688 __ Set(eax, Immediate(argc_)); 4698 __ Set(eax, Immediate(argc_));
4689 __ Set(ebx, Immediate(0)); 4699 __ Set(ebx, Immediate(0));
4690 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 4700 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
4691 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 4701 Handle<Code> adaptor(Isolate::Current()->builtins()->builtin(
4702 Builtins::ArgumentsAdaptorTrampoline));
4692 __ jmp(adaptor, RelocInfo::CODE_TARGET); 4703 __ jmp(adaptor, RelocInfo::CODE_TARGET);
4693 } 4704 }
4694 4705
4695 4706
4696 bool CEntryStub::NeedsImmovableCode() { 4707 bool CEntryStub::NeedsImmovableCode() {
4697 return false; 4708 return false;
4698 } 4709 }
4699 4710
4700 4711
4701 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { 4712 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4735 4746
4736 ExternalReference scope_depth = 4747 ExternalReference scope_depth =
4737 ExternalReference::heap_always_allocate_scope_depth(); 4748 ExternalReference::heap_always_allocate_scope_depth();
4738 if (always_allocate_scope) { 4749 if (always_allocate_scope) {
4739 __ inc(Operand::StaticVariable(scope_depth)); 4750 __ inc(Operand::StaticVariable(scope_depth));
4740 } 4751 }
4741 4752
4742 // Call C function. 4753 // Call C function.
4743 __ mov(Operand(esp, 0 * kPointerSize), edi); // argc. 4754 __ mov(Operand(esp, 0 * kPointerSize), edi); // argc.
4744 __ mov(Operand(esp, 1 * kPointerSize), esi); // argv. 4755 __ mov(Operand(esp, 1 * kPointerSize), esi); // argv.
4756 __ mov(Operand(esp, 2 * kPointerSize),
4757 Immediate(ExternalReference::isolate_address()));
4745 __ call(Operand(ebx)); 4758 __ call(Operand(ebx));
4746 // Result is in eax or edx:eax - do not destroy these registers! 4759 // Result is in eax or edx:eax - do not destroy these registers!
4747 4760
4748 if (always_allocate_scope) { 4761 if (always_allocate_scope) {
4749 __ dec(Operand::StaticVariable(scope_depth)); 4762 __ dec(Operand::StaticVariable(scope_depth));
4750 } 4763 }
4751 4764
4752 // Make sure we're not trying to return 'the hole' from the runtime 4765 // Make sure we're not trying to return 'the hole' from the runtime
4753 // call as this may lead to crashes in the IC code later. 4766 // call as this may lead to crashes in the IC code later.
4754 if (FLAG_debug_code) { 4767 if (FLAG_debug_code) {
4755 NearLabel okay; 4768 NearLabel okay;
4756 __ cmp(eax, Factory::the_hole_value()); 4769 __ cmp(eax, FACTORY->the_hole_value());
4757 __ j(not_equal, &okay); 4770 __ j(not_equal, &okay);
4758 __ int3(); 4771 __ int3();
4759 __ bind(&okay); 4772 __ bind(&okay);
4760 } 4773 }
4761 4774
4762 // Check for failure result. 4775 // Check for failure result.
4763 Label failure_returned; 4776 Label failure_returned;
4764 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 4777 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
4765 __ lea(ecx, Operand(eax, 1)); 4778 __ lea(ecx, Operand(eax, 1));
4766 // Lower 2 bits of ecx are 0 iff eax has failure tag. 4779 // Lower 2 bits of ecx are 0 iff eax has failure tag.
4767 __ test(ecx, Immediate(kFailureTagMask)); 4780 __ test(ecx, Immediate(kFailureTagMask));
4768 __ j(zero, &failure_returned, not_taken); 4781 __ j(zero, &failure_returned, not_taken);
4769 4782
4770 ExternalReference pending_exception_address(Top::k_pending_exception_address); 4783 ExternalReference pending_exception_address(
4784 Isolate::k_pending_exception_address);
4771 4785
4772 // Check that there is no pending exception, otherwise we 4786 // Check that there is no pending exception, otherwise we
4773 // should have returned some failure value. 4787 // should have returned some failure value.
4774 if (FLAG_debug_code) { 4788 if (FLAG_debug_code) {
4775 __ push(edx); 4789 __ push(edx);
4776 __ mov(edx, Operand::StaticVariable( 4790 __ mov(edx, Operand::StaticVariable(
4777 ExternalReference::the_hole_value_location())); 4791 ExternalReference::the_hole_value_location()));
4778 NearLabel okay; 4792 NearLabel okay;
4779 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); 4793 __ cmp(edx, Operand::StaticVariable(pending_exception_address));
4780 // Cannot use check here as it attempts to generate call into runtime. 4794 // Cannot use check here as it attempts to generate call into runtime.
(...skipping 21 matching lines...) Expand all
4802 __ j(equal, throw_out_of_memory_exception); 4816 __ j(equal, throw_out_of_memory_exception);
4803 4817
4804 // Retrieve the pending exception and clear the variable. 4818 // Retrieve the pending exception and clear the variable.
4805 __ mov(eax, Operand::StaticVariable(pending_exception_address)); 4819 __ mov(eax, Operand::StaticVariable(pending_exception_address));
4806 __ mov(edx, 4820 __ mov(edx,
4807 Operand::StaticVariable(ExternalReference::the_hole_value_location())); 4821 Operand::StaticVariable(ExternalReference::the_hole_value_location()));
4808 __ mov(Operand::StaticVariable(pending_exception_address), edx); 4822 __ mov(Operand::StaticVariable(pending_exception_address), edx);
4809 4823
4810 // Special handling of termination exceptions which are uncatchable 4824 // Special handling of termination exceptions which are uncatchable
4811 // by javascript code. 4825 // by javascript code.
4812 __ cmp(eax, Factory::termination_exception()); 4826 __ cmp(eax, FACTORY->termination_exception());
4813 __ j(equal, throw_termination_exception); 4827 __ j(equal, throw_termination_exception);
4814 4828
4815 // Handle normal exception. 4829 // Handle normal exception.
4816 __ jmp(throw_normal_exception); 4830 __ jmp(throw_normal_exception);
4817 4831
4818 // Retry. 4832 // Retry.
4819 __ bind(&retry); 4833 __ bind(&retry);
4820 } 4834 }
4821 4835
4822 4836
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
4902 // Push marker in two places. 4916 // Push marker in two places.
4903 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 4917 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
4904 __ push(Immediate(Smi::FromInt(marker))); // context slot 4918 __ push(Immediate(Smi::FromInt(marker))); // context slot
4905 __ push(Immediate(Smi::FromInt(marker))); // function slot 4919 __ push(Immediate(Smi::FromInt(marker))); // function slot
4906 // Save callee-saved registers (C calling conventions). 4920 // Save callee-saved registers (C calling conventions).
4907 __ push(edi); 4921 __ push(edi);
4908 __ push(esi); 4922 __ push(esi);
4909 __ push(ebx); 4923 __ push(ebx);
4910 4924
4911 // Save copies of the top frame descriptor on the stack. 4925 // Save copies of the top frame descriptor on the stack.
4912 ExternalReference c_entry_fp(Top::k_c_entry_fp_address); 4926 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address);
4913 __ push(Operand::StaticVariable(c_entry_fp)); 4927 __ push(Operand::StaticVariable(c_entry_fp));
4914 4928
4915 #ifdef ENABLE_LOGGING_AND_PROFILING 4929 #ifdef ENABLE_LOGGING_AND_PROFILING
4916 // If this is the outermost JS call, set js_entry_sp value. 4930 // If this is the outermost JS call, set js_entry_sp value.
4917 ExternalReference js_entry_sp(Top::k_js_entry_sp_address); 4931 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address);
4918 __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0)); 4932 __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0));
4919 __ j(not_equal, &not_outermost_js); 4933 __ j(not_equal, &not_outermost_js);
4920 __ mov(Operand::StaticVariable(js_entry_sp), ebp); 4934 __ mov(Operand::StaticVariable(js_entry_sp), ebp);
4921 __ bind(&not_outermost_js); 4935 __ bind(&not_outermost_js);
4922 #endif 4936 #endif
4923 4937
4924 // Call a faked try-block that does the invoke. 4938 // Call a faked try-block that does the invoke.
4925 __ call(&invoke); 4939 __ call(&invoke);
4926 4940
4927 // Caught exception: Store result (exception) in the pending 4941 // Caught exception: Store result (exception) in the pending
4928 // exception field in the JSEnv and return a failure sentinel. 4942 // exception field in the JSEnv and return a failure sentinel.
4929 ExternalReference pending_exception(Top::k_pending_exception_address); 4943 ExternalReference pending_exception(Isolate::k_pending_exception_address);
4930 __ mov(Operand::StaticVariable(pending_exception), eax); 4944 __ mov(Operand::StaticVariable(pending_exception), eax);
4931 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception())); 4945 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
4932 __ jmp(&exit); 4946 __ jmp(&exit);
4933 4947
4934 // Invoke: Link this frame into the handler chain. 4948 // Invoke: Link this frame into the handler chain.
4935 __ bind(&invoke); 4949 __ bind(&invoke);
4936 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); 4950 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
4937 4951
4938 // Clear any pending exceptions. 4952 // Clear any pending exceptions.
4939 __ mov(edx, 4953 __ mov(edx,
(...skipping 12 matching lines...) Expand all
4952 __ mov(edx, Immediate(construct_entry)); 4966 __ mov(edx, Immediate(construct_entry));
4953 } else { 4967 } else {
4954 ExternalReference entry(Builtins::JSEntryTrampoline); 4968 ExternalReference entry(Builtins::JSEntryTrampoline);
4955 __ mov(edx, Immediate(entry)); 4969 __ mov(edx, Immediate(entry));
4956 } 4970 }
4957 __ mov(edx, Operand(edx, 0)); // deref address 4971 __ mov(edx, Operand(edx, 0)); // deref address
4958 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); 4972 __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
4959 __ call(Operand(edx)); 4973 __ call(Operand(edx));
4960 4974
4961 // Unlink this frame from the handler chain. 4975 // Unlink this frame from the handler chain.
4962 __ pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address))); 4976 __ pop(Operand::StaticVariable(ExternalReference(
4977 Isolate::k_handler_address)));
4963 // Pop next_sp. 4978 // Pop next_sp.
4964 __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); 4979 __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
4965 4980
4966 #ifdef ENABLE_LOGGING_AND_PROFILING 4981 #ifdef ENABLE_LOGGING_AND_PROFILING
4967 // If current EBP value is the same as js_entry_sp value, it means that 4982 // If current EBP value is the same as js_entry_sp value, it means that
4968 // the current function is the outermost. 4983 // the current function is the outermost.
4969 __ cmp(ebp, Operand::StaticVariable(js_entry_sp)); 4984 __ cmp(ebp, Operand::StaticVariable(js_entry_sp));
4970 __ j(not_equal, &not_outermost_js_2); 4985 __ j(not_equal, &not_outermost_js_2);
4971 __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0)); 4986 __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0));
4972 __ bind(&not_outermost_js_2); 4987 __ bind(&not_outermost_js_2);
4973 #endif 4988 #endif
4974 4989
4975 // Restore the top frame descriptor from the stack. 4990 // Restore the top frame descriptor from the stack.
4976 __ bind(&exit); 4991 __ bind(&exit);
4977 __ pop(Operand::StaticVariable(ExternalReference(Top::k_c_entry_fp_address))); 4992 __ pop(Operand::StaticVariable(ExternalReference(
4993 Isolate::k_c_entry_fp_address)));
4978 4994
4979 // Restore callee-saved registers (C calling conventions). 4995 // Restore callee-saved registers (C calling conventions).
4980 __ pop(ebx); 4996 __ pop(ebx);
4981 __ pop(esi); 4997 __ pop(esi);
4982 __ pop(edi); 4998 __ pop(edi);
4983 __ add(Operand(esp), Immediate(2 * kPointerSize)); // remove markers 4999 __ add(Operand(esp), Immediate(2 * kPointerSize)); // remove markers
4984 5000
4985 // Restore frame pointer and return. 5001 // Restore frame pointer and return.
4986 __ pop(ebp); 5002 __ pop(ebp);
4987 __ ret(0); 5003 __ ret(0);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
5092 __ mov(Operand(scratch, kDeltaToCmpImmediate), map); 5108 __ mov(Operand(scratch, kDeltaToCmpImmediate), map);
5093 } 5109 }
5094 5110
5095 // Loop through the prototype chain of the object looking for the function 5111 // Loop through the prototype chain of the object looking for the function
5096 // prototype. 5112 // prototype.
5097 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); 5113 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset));
5098 NearLabel loop, is_instance, is_not_instance; 5114 NearLabel loop, is_instance, is_not_instance;
5099 __ bind(&loop); 5115 __ bind(&loop);
5100 __ cmp(scratch, Operand(prototype)); 5116 __ cmp(scratch, Operand(prototype));
5101 __ j(equal, &is_instance); 5117 __ j(equal, &is_instance);
5102 __ cmp(Operand(scratch), Immediate(Factory::null_value())); 5118 __ cmp(Operand(scratch), Immediate(FACTORY->null_value()));
5103 __ j(equal, &is_not_instance); 5119 __ j(equal, &is_not_instance);
5104 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 5120 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
5105 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); 5121 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
5106 __ jmp(&loop); 5122 __ jmp(&loop);
5107 5123
5108 __ bind(&is_instance); 5124 __ bind(&is_instance);
5109 if (!HasCallSiteInlineCheck()) { 5125 if (!HasCallSiteInlineCheck()) {
5110 __ Set(eax, Immediate(0)); 5126 __ Set(eax, Immediate(0));
5111 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); 5127 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
5112 __ mov(Operand::StaticArray(scratch, 5128 __ mov(Operand::StaticArray(scratch,
5113 times_pointer_size, roots_address), eax); 5129 times_pointer_size, roots_address), eax);
5114 } else { 5130 } else {
5115 // Get return address and delta to inlined map check. 5131 // Get return address and delta to inlined map check.
5116 __ mov(eax, Factory::true_value()); 5132 __ mov(eax, FACTORY->true_value());
5117 __ mov(scratch, Operand(esp, 0 * kPointerSize)); 5133 __ mov(scratch, Operand(esp, 0 * kPointerSize));
5118 __ sub(scratch, Operand(esp, 1 * kPointerSize)); 5134 __ sub(scratch, Operand(esp, 1 * kPointerSize));
5119 if (FLAG_debug_code) { 5135 if (FLAG_debug_code) {
5120 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); 5136 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
5121 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); 5137 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
5122 } 5138 }
5123 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); 5139 __ mov(Operand(scratch, kDeltaToMovImmediate), eax);
5124 if (!ReturnTrueFalseObject()) { 5140 if (!ReturnTrueFalseObject()) {
5125 __ Set(eax, Immediate(0)); 5141 __ Set(eax, Immediate(0));
5126 } 5142 }
5127 } 5143 }
5128 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 5144 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5129 5145
5130 __ bind(&is_not_instance); 5146 __ bind(&is_not_instance);
5131 if (!HasCallSiteInlineCheck()) { 5147 if (!HasCallSiteInlineCheck()) {
5132 __ Set(eax, Immediate(Smi::FromInt(1))); 5148 __ Set(eax, Immediate(Smi::FromInt(1)));
5133 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); 5149 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
5134 __ mov(Operand::StaticArray( 5150 __ mov(Operand::StaticArray(
5135 scratch, times_pointer_size, roots_address), eax); 5151 scratch, times_pointer_size, roots_address), eax);
5136 } else { 5152 } else {
5137 // Get return address and delta to inlined map check. 5153 // Get return address and delta to inlined map check.
5138 __ mov(eax, Factory::false_value()); 5154 __ mov(eax, FACTORY->false_value());
5139 __ mov(scratch, Operand(esp, 0 * kPointerSize)); 5155 __ mov(scratch, Operand(esp, 0 * kPointerSize));
5140 __ sub(scratch, Operand(esp, 1 * kPointerSize)); 5156 __ sub(scratch, Operand(esp, 1 * kPointerSize));
5141 if (FLAG_debug_code) { 5157 if (FLAG_debug_code) {
5142 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); 5158 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
5143 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); 5159 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
5144 } 5160 }
5145 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); 5161 __ mov(Operand(scratch, kDeltaToMovImmediate), eax);
5146 if (!ReturnTrueFalseObject()) { 5162 if (!ReturnTrueFalseObject()) {
5147 __ Set(eax, Immediate(Smi::FromInt(1))); 5163 __ Set(eax, Immediate(Smi::FromInt(1)));
5148 } 5164 }
5149 } 5165 }
5150 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 5166 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5151 5167
5152 Label object_not_null, object_not_null_or_smi; 5168 Label object_not_null, object_not_null_or_smi;
5153 __ bind(&not_js_object); 5169 __ bind(&not_js_object);
5154 // Before null, smi and string value checks, check that the rhs is a function 5170 // Before null, smi and string value checks, check that the rhs is a function
5155 // as for a non-function rhs an exception needs to be thrown. 5171 // as for a non-function rhs an exception needs to be thrown.
5156 __ test(function, Immediate(kSmiTagMask)); 5172 __ test(function, Immediate(kSmiTagMask));
5157 __ j(zero, &slow, not_taken); 5173 __ j(zero, &slow, not_taken);
5158 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); 5174 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
5159 __ j(not_equal, &slow, not_taken); 5175 __ j(not_equal, &slow, not_taken);
5160 5176
5161 // Null is not instance of anything. 5177 // Null is not instance of anything.
5162 __ cmp(object, Factory::null_value()); 5178 __ cmp(object, FACTORY->null_value());
5163 __ j(not_equal, &object_not_null); 5179 __ j(not_equal, &object_not_null);
5164 __ Set(eax, Immediate(Smi::FromInt(1))); 5180 __ Set(eax, Immediate(Smi::FromInt(1)));
5165 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 5181 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5166 5182
5167 __ bind(&object_not_null); 5183 __ bind(&object_not_null);
5168 // Smi values is not instance of anything. 5184 // Smi values is not instance of anything.
5169 __ test(object, Immediate(kSmiTagMask)); 5185 __ test(object, Immediate(kSmiTagMask));
5170 __ j(not_zero, &object_not_null_or_smi, not_taken); 5186 __ j(not_zero, &object_not_null_or_smi, not_taken);
5171 __ Set(eax, Immediate(Smi::FromInt(1))); 5187 __ Set(eax, Immediate(Smi::FromInt(1)));
5172 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 5188 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
(...skipping 20 matching lines...) Expand all
5193 } else { 5209 } else {
5194 // Call the builtin and convert 0/1 to true/false. 5210 // Call the builtin and convert 0/1 to true/false.
5195 __ EnterInternalFrame(); 5211 __ EnterInternalFrame();
5196 __ push(object); 5212 __ push(object);
5197 __ push(function); 5213 __ push(function);
5198 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 5214 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
5199 __ LeaveInternalFrame(); 5215 __ LeaveInternalFrame();
5200 NearLabel true_value, done; 5216 NearLabel true_value, done;
5201 __ test(eax, Operand(eax)); 5217 __ test(eax, Operand(eax));
5202 __ j(zero, &true_value); 5218 __ j(zero, &true_value);
5203 __ mov(eax, Factory::false_value()); 5219 __ mov(eax, FACTORY->false_value());
5204 __ jmp(&done); 5220 __ jmp(&done);
5205 __ bind(&true_value); 5221 __ bind(&true_value);
5206 __ mov(eax, Factory::true_value()); 5222 __ mov(eax, FACTORY->true_value());
5207 __ bind(&done); 5223 __ bind(&done);
5208 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 5224 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5209 } 5225 }
5210 } 5226 }
5211 5227
5212 5228
5213 Register InstanceofStub::left() { return eax; } 5229 Register InstanceofStub::left() { return eax; }
5214 5230
5215 5231
5216 Register InstanceofStub::right() { return edx; } 5232 Register InstanceofStub::right() { return edx; }
(...skipping 14 matching lines...) Expand all
5231 } 5247 }
5232 5248
5233 5249
5234 // Unfortunately you have to run without snapshots to see most of these 5250 // Unfortunately you have to run without snapshots to see most of these
5235 // names in the profile since most compare stubs end up in the snapshot. 5251 // names in the profile since most compare stubs end up in the snapshot.
5236 const char* CompareStub::GetName() { 5252 const char* CompareStub::GetName() {
5237 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); 5253 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
5238 5254
5239 if (name_ != NULL) return name_; 5255 if (name_ != NULL) return name_;
5240 const int kMaxNameLength = 100; 5256 const int kMaxNameLength = 100;
5241 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength); 5257 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
5258 kMaxNameLength);
5242 if (name_ == NULL) return "OOM"; 5259 if (name_ == NULL) return "OOM";
5243 5260
5244 const char* cc_name; 5261 const char* cc_name;
5245 switch (cc_) { 5262 switch (cc_) {
5246 case less: cc_name = "LT"; break; 5263 case less: cc_name = "LT"; break;
5247 case greater: cc_name = "GT"; break; 5264 case greater: cc_name = "GT"; break;
5248 case less_equal: cc_name = "LE"; break; 5265 case less_equal: cc_name = "LE"; break;
5249 case greater_equal: cc_name = "GE"; break; 5266 case greater_equal: cc_name = "GE"; break;
5250 case equal: cc_name = "EQ"; break; 5267 case equal: cc_name = "EQ"; break;
5251 case not_equal: cc_name = "NE"; break; 5268 case not_equal: cc_name = "NE"; break;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
5324 // Handle non-flat strings. 5341 // Handle non-flat strings.
5325 __ test(result_, Immediate(kIsConsStringMask)); 5342 __ test(result_, Immediate(kIsConsStringMask));
5326 __ j(zero, &call_runtime_); 5343 __ j(zero, &call_runtime_);
5327 5344
5328 // ConsString. 5345 // ConsString.
5329 // Check whether the right hand side is the empty string (i.e. if 5346 // Check whether the right hand side is the empty string (i.e. if
5330 // this is really a flat string in a cons string). If that is not 5347 // this is really a flat string in a cons string). If that is not
5331 // the case we would rather go to the runtime system now to flatten 5348 // the case we would rather go to the runtime system now to flatten
5332 // the string. 5349 // the string.
5333 __ cmp(FieldOperand(object_, ConsString::kSecondOffset), 5350 __ cmp(FieldOperand(object_, ConsString::kSecondOffset),
5334 Immediate(Factory::empty_string())); 5351 Immediate(FACTORY->empty_string()));
5335 __ j(not_equal, &call_runtime_); 5352 __ j(not_equal, &call_runtime_);
5336 // Get the first of the two strings and load its instance type. 5353 // Get the first of the two strings and load its instance type.
5337 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset)); 5354 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset));
5338 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 5355 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
5339 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 5356 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
5340 // If the first cons component is also non-flat, then go to runtime. 5357 // If the first cons component is also non-flat, then go to runtime.
5341 STATIC_ASSERT(kSeqStringTag == 0); 5358 STATIC_ASSERT(kSeqStringTag == 0);
5342 __ test(result_, Immediate(kStringRepresentationMask)); 5359 __ test(result_, Immediate(kStringRepresentationMask));
5343 __ j(not_zero, &call_runtime_); 5360 __ j(not_zero, &call_runtime_);
5344 5361
(...skipping 24 matching lines...) Expand all
5369 } 5386 }
5370 5387
5371 5388
5372 void StringCharCodeAtGenerator::GenerateSlow( 5389 void StringCharCodeAtGenerator::GenerateSlow(
5373 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { 5390 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
5374 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); 5391 __ Abort("Unexpected fallthrough to CharCodeAt slow case");
5375 5392
5376 // Index is not a smi. 5393 // Index is not a smi.
5377 __ bind(&index_not_smi_); 5394 __ bind(&index_not_smi_);
5378 // If index is a heap number, try converting it to an integer. 5395 // If index is a heap number, try converting it to an integer.
5379 __ CheckMap(index_, Factory::heap_number_map(), index_not_number_, true); 5396 __ CheckMap(index_, FACTORY->heap_number_map(), index_not_number_, true);
5380 call_helper.BeforeCall(masm); 5397 call_helper.BeforeCall(masm);
5381 __ push(object_); 5398 __ push(object_);
5382 __ push(index_); 5399 __ push(index_);
5383 __ push(index_); // Consumed by runtime conversion function. 5400 __ push(index_); // Consumed by runtime conversion function.
5384 if (index_flags_ == STRING_INDEX_IS_NUMBER) { 5401 if (index_flags_ == STRING_INDEX_IS_NUMBER) {
5385 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 5402 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
5386 } else { 5403 } else {
5387 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 5404 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
5388 // NumberToSmi discards numbers that are not exact integers. 5405 // NumberToSmi discards numbers that are not exact integers.
5389 __ CallRuntime(Runtime::kNumberToSmi, 1); 5406 __ CallRuntime(Runtime::kNumberToSmi, 1);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
5430 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 5447 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
5431 // Fast case of Heap::LookupSingleCharacterStringFromCode. 5448 // Fast case of Heap::LookupSingleCharacterStringFromCode.
5432 STATIC_ASSERT(kSmiTag == 0); 5449 STATIC_ASSERT(kSmiTag == 0);
5433 STATIC_ASSERT(kSmiShiftSize == 0); 5450 STATIC_ASSERT(kSmiShiftSize == 0);
5434 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); 5451 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
5435 __ test(code_, 5452 __ test(code_,
5436 Immediate(kSmiTagMask | 5453 Immediate(kSmiTagMask |
5437 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); 5454 ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
5438 __ j(not_zero, &slow_case_, not_taken); 5455 __ j(not_zero, &slow_case_, not_taken);
5439 5456
5440 __ Set(result_, Immediate(Factory::single_character_string_cache())); 5457 __ Set(result_, Immediate(FACTORY->single_character_string_cache()));
5441 STATIC_ASSERT(kSmiTag == 0); 5458 STATIC_ASSERT(kSmiTag == 0);
5442 STATIC_ASSERT(kSmiTagSize == 1); 5459 STATIC_ASSERT(kSmiTagSize == 1);
5443 STATIC_ASSERT(kSmiShiftSize == 0); 5460 STATIC_ASSERT(kSmiShiftSize == 0);
5444 // At this point code register contains smi tagged ascii char code. 5461 // At this point code register contains smi tagged ascii char code.
5445 __ mov(result_, FieldOperand(result_, 5462 __ mov(result_, FieldOperand(result_,
5446 code_, times_half_pointer_size, 5463 code_, times_half_pointer_size,
5447 FixedArray::kHeaderSize)); 5464 FixedArray::kHeaderSize));
5448 __ cmp(result_, Factory::undefined_value()); 5465 __ cmp(result_, FACTORY->undefined_value());
5449 __ j(equal, &slow_case_, not_taken); 5466 __ j(equal, &slow_case_, not_taken);
5450 __ bind(&exit_); 5467 __ bind(&exit_);
5451 } 5468 }
5452 5469
5453 5470
5454 void StringCharFromCodeGenerator::GenerateSlow( 5471 void StringCharFromCodeGenerator::GenerateSlow(
5455 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { 5472 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
5456 __ Abort("Unexpected fallthrough to CharFromCode slow case"); 5473 __ Abort("Unexpected fallthrough to CharFromCode slow case");
5457 5474
5458 __ bind(&slow_case_); 5475 __ bind(&slow_case_);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
5524 // Both arguments are strings. 5541 // Both arguments are strings.
5525 // eax: first string 5542 // eax: first string
5526 // edx: second string 5543 // edx: second string
5527 // Check if either of the strings are empty. In that case return the other. 5544 // Check if either of the strings are empty. In that case return the other.
5528 NearLabel second_not_zero_length, both_not_zero_length; 5545 NearLabel second_not_zero_length, both_not_zero_length;
5529 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); 5546 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
5530 STATIC_ASSERT(kSmiTag == 0); 5547 STATIC_ASSERT(kSmiTag == 0);
5531 __ test(ecx, Operand(ecx)); 5548 __ test(ecx, Operand(ecx));
5532 __ j(not_zero, &second_not_zero_length); 5549 __ j(not_zero, &second_not_zero_length);
5533 // Second string is empty, result is first string which is already in eax. 5550 // Second string is empty, result is first string which is already in eax.
5534 __ IncrementCounter(&Counters::string_add_native, 1); 5551 __ IncrementCounter(COUNTERS->string_add_native(), 1);
5535 __ ret(2 * kPointerSize); 5552 __ ret(2 * kPointerSize);
5536 __ bind(&second_not_zero_length); 5553 __ bind(&second_not_zero_length);
5537 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); 5554 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
5538 STATIC_ASSERT(kSmiTag == 0); 5555 STATIC_ASSERT(kSmiTag == 0);
5539 __ test(ebx, Operand(ebx)); 5556 __ test(ebx, Operand(ebx));
5540 __ j(not_zero, &both_not_zero_length); 5557 __ j(not_zero, &both_not_zero_length);
5541 // First string is empty, result is second string which is in edx. 5558 // First string is empty, result is second string which is in edx.
5542 __ mov(eax, edx); 5559 __ mov(eax, edx);
5543 __ IncrementCounter(&Counters::string_add_native, 1); 5560 __ IncrementCounter(COUNTERS->string_add_native(), 1);
5544 __ ret(2 * kPointerSize); 5561 __ ret(2 * kPointerSize);
5545 5562
5546 // Both strings are non-empty. 5563 // Both strings are non-empty.
5547 // eax: first string 5564 // eax: first string
5548 // ebx: length of first string as a smi 5565 // ebx: length of first string as a smi
5549 // ecx: length of second string as a smi 5566 // ecx: length of second string as a smi
5550 // edx: second string 5567 // edx: second string
5551 // Look at the length of the result of adding the two strings. 5568 // Look at the length of the result of adding the two strings.
5552 Label string_add_flat_result, longer_than_two; 5569 Label string_add_flat_result, longer_than_two;
5553 __ bind(&both_not_zero_length); 5570 __ bind(&both_not_zero_length);
(...skipping 13 matching lines...) Expand all
5567 // Get the two characters forming the new string. 5584 // Get the two characters forming the new string.
5568 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 5585 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
5569 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 5586 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
5570 5587
5571 // Try to lookup two character string in symbol table. If it is not found 5588 // Try to lookup two character string in symbol table. If it is not found
5572 // just allocate a new one. 5589 // just allocate a new one.
5573 Label make_two_character_string, make_two_character_string_no_reload; 5590 Label make_two_character_string, make_two_character_string_no_reload;
5574 StringHelper::GenerateTwoCharacterSymbolTableProbe( 5591 StringHelper::GenerateTwoCharacterSymbolTableProbe(
5575 masm, ebx, ecx, eax, edx, edi, 5592 masm, ebx, ecx, eax, edx, edi,
5576 &make_two_character_string_no_reload, &make_two_character_string); 5593 &make_two_character_string_no_reload, &make_two_character_string);
5577 __ IncrementCounter(&Counters::string_add_native, 1); 5594 __ IncrementCounter(COUNTERS->string_add_native(), 1);
5578 __ ret(2 * kPointerSize); 5595 __ ret(2 * kPointerSize);
5579 5596
5580 // Allocate a two character string. 5597 // Allocate a two character string.
5581 __ bind(&make_two_character_string); 5598 __ bind(&make_two_character_string);
5582 // Reload the arguments. 5599 // Reload the arguments.
5583 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 5600 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
5584 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 5601 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
5585 // Get the two characters forming the new string. 5602 // Get the two characters forming the new string.
5586 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 5603 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
5587 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 5604 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
5588 __ bind(&make_two_character_string_no_reload); 5605 __ bind(&make_two_character_string_no_reload);
5589 __ IncrementCounter(&Counters::string_add_make_two_char, 1); 5606 __ IncrementCounter(COUNTERS->string_add_make_two_char(), 1);
5590 __ AllocateAsciiString(eax, // Result. 5607 __ AllocateAsciiString(eax, // Result.
5591 2, // Length. 5608 2, // Length.
5592 edi, // Scratch 1. 5609 edi, // Scratch 1.
5593 edx, // Scratch 2. 5610 edx, // Scratch 2.
5594 &string_add_runtime); 5611 &string_add_runtime);
5595 // Pack both characters in ebx. 5612 // Pack both characters in ebx.
5596 __ shl(ecx, kBitsPerByte); 5613 __ shl(ecx, kBitsPerByte);
5597 __ or_(ebx, Operand(ecx)); 5614 __ or_(ebx, Operand(ecx));
5598 // Set the characters in the new string. 5615 // Set the characters in the new string.
5599 __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx); 5616 __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx);
5600 __ IncrementCounter(&Counters::string_add_native, 1); 5617 __ IncrementCounter(COUNTERS->string_add_native(), 1);
5601 __ ret(2 * kPointerSize); 5618 __ ret(2 * kPointerSize);
5602 5619
5603 __ bind(&longer_than_two); 5620 __ bind(&longer_than_two);
5604 // Check if resulting string will be flat. 5621 // Check if resulting string will be flat.
5605 __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength))); 5622 __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength)));
5606 __ j(below, &string_add_flat_result); 5623 __ j(below, &string_add_flat_result);
5607 5624
5608 // If result is not supposed to be flat allocate a cons string object. If both 5625 // If result is not supposed to be flat allocate a cons string object. If both
5609 // strings are ascii the result is an ascii cons string. 5626 // strings are ascii the result is an ascii cons string.
5610 Label non_ascii, allocated, ascii_data; 5627 Label non_ascii, allocated, ascii_data;
(...skipping 10 matching lines...) Expand all
5621 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime); 5638 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime);
5622 __ bind(&allocated); 5639 __ bind(&allocated);
5623 // Fill the fields of the cons string. 5640 // Fill the fields of the cons string.
5624 if (FLAG_debug_code) __ AbortIfNotSmi(ebx); 5641 if (FLAG_debug_code) __ AbortIfNotSmi(ebx);
5625 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); 5642 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
5626 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), 5643 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
5627 Immediate(String::kEmptyHashField)); 5644 Immediate(String::kEmptyHashField));
5628 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); 5645 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
5629 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); 5646 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
5630 __ mov(eax, ecx); 5647 __ mov(eax, ecx);
5631 __ IncrementCounter(&Counters::string_add_native, 1); 5648 __ IncrementCounter(COUNTERS->string_add_native(), 1);
5632 __ ret(2 * kPointerSize); 5649 __ ret(2 * kPointerSize);
5633 __ bind(&non_ascii); 5650 __ bind(&non_ascii);
5634 // At least one of the strings is two-byte. Check whether it happens 5651 // At least one of the strings is two-byte. Check whether it happens
5635 // to contain only ascii characters. 5652 // to contain only ascii characters.
5636 // ecx: first instance type AND second instance type. 5653 // ecx: first instance type AND second instance type.
5637 // edi: second instance type. 5654 // edi: second instance type.
5638 __ test(ecx, Immediate(kAsciiDataHintMask)); 5655 __ test(ecx, Immediate(kAsciiDataHintMask));
5639 __ j(not_zero, &ascii_data); 5656 __ j(not_zero, &ascii_data);
5640 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 5657 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
5641 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 5658 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
5698 // Load second argument and locate first character. 5715 // Load second argument and locate first character.
5699 __ mov(edx, Operand(esp, 1 * kPointerSize)); 5716 __ mov(edx, Operand(esp, 1 * kPointerSize));
5700 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 5717 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5701 __ SmiUntag(edi); 5718 __ SmiUntag(edi);
5702 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 5719 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5703 // eax: result string 5720 // eax: result string
5704 // ecx: next character of result 5721 // ecx: next character of result
5705 // edx: first char of second argument 5722 // edx: first char of second argument
5706 // edi: length of second argument 5723 // edi: length of second argument
5707 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 5724 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
5708 __ IncrementCounter(&Counters::string_add_native, 1); 5725 __ IncrementCounter(COUNTERS->string_add_native(), 1);
5709 __ ret(2 * kPointerSize); 5726 __ ret(2 * kPointerSize);
5710 5727
5711 // Handle creating a flat two byte result. 5728 // Handle creating a flat two byte result.
5712 // eax: first string - known to be two byte 5729 // eax: first string - known to be two byte
5713 // ebx: length of resulting flat string as a smi 5730 // ebx: length of resulting flat string as a smi
5714 // edx: second string 5731 // edx: second string
5715 __ bind(&non_ascii_string_add_flat_result); 5732 __ bind(&non_ascii_string_add_flat_result);
5716 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 5733 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
5717 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); 5734 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
5718 __ j(not_zero, &string_add_runtime); 5735 __ j(not_zero, &string_add_runtime);
(...skipping 20 matching lines...) Expand all
5739 // Load second argument and locate first character. 5756 // Load second argument and locate first character.
5740 __ mov(edx, Operand(esp, 1 * kPointerSize)); 5757 __ mov(edx, Operand(esp, 1 * kPointerSize));
5741 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 5758 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5742 __ SmiUntag(edi); 5759 __ SmiUntag(edi);
5743 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 5760 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5744 // eax: result string 5761 // eax: result string
5745 // ecx: next character of result 5762 // ecx: next character of result
5746 // edx: first char of second argument 5763 // edx: first char of second argument
5747 // edi: length of second argument 5764 // edi: length of second argument
5748 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 5765 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
5749 __ IncrementCounter(&Counters::string_add_native, 1); 5766 __ IncrementCounter(COUNTERS->string_add_native(), 1);
5750 __ ret(2 * kPointerSize); 5767 __ ret(2 * kPointerSize);
5751 5768
5752 // Just jump to runtime to add the two strings. 5769 // Just jump to runtime to add the two strings.
5753 __ bind(&string_add_runtime); 5770 __ bind(&string_add_runtime);
5754 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 5771 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
5755 5772
5756 if (call_builtin.is_linked()) { 5773 if (call_builtin.is_linked()) {
5757 __ bind(&call_builtin); 5774 __ bind(&call_builtin);
5758 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); 5775 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
5759 } 5776 }
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
5964 // Load the entry from the symbol table. 5981 // Load the entry from the symbol table.
5965 Register candidate = scratch; // Scratch register contains candidate. 5982 Register candidate = scratch; // Scratch register contains candidate.
5966 STATIC_ASSERT(SymbolTable::kEntrySize == 1); 5983 STATIC_ASSERT(SymbolTable::kEntrySize == 1);
5967 __ mov(candidate, 5984 __ mov(candidate,
5968 FieldOperand(symbol_table, 5985 FieldOperand(symbol_table,
5969 scratch, 5986 scratch,
5970 times_pointer_size, 5987 times_pointer_size,
5971 SymbolTable::kElementsStartOffset)); 5988 SymbolTable::kElementsStartOffset));
5972 5989
5973 // If entry is undefined no string with this hash can be found. 5990 // If entry is undefined no string with this hash can be found.
5974 __ cmp(candidate, Factory::undefined_value()); 5991 __ cmp(candidate, FACTORY->undefined_value());
5975 __ j(equal, not_found); 5992 __ j(equal, not_found);
5976 __ cmp(candidate, Factory::null_value()); 5993 __ cmp(candidate, FACTORY->null_value());
5977 __ j(equal, &next_probe[i]); 5994 __ j(equal, &next_probe[i]);
5978 5995
5979 // If length is not 2 the string is not a candidate. 5996 // If length is not 2 the string is not a candidate.
5980 __ cmp(FieldOperand(candidate, String::kLengthOffset), 5997 __ cmp(FieldOperand(candidate, String::kLengthOffset),
5981 Immediate(Smi::FromInt(2))); 5998 Immediate(Smi::FromInt(2)));
5982 __ j(not_equal, &next_probe[i]); 5999 __ j(not_equal, &next_probe[i]);
5983 6000
5984 // As we are out of registers save the mask on the stack and use that 6001 // As we are out of registers save the mask on the stack and use that
5985 // register as a temporary. 6002 // register as a temporary.
5986 __ push(mask); 6003 __ push(mask);
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
6163 __ SmiUntag(ebx); 6180 __ SmiUntag(ebx);
6164 __ add(esi, Operand(ebx)); 6181 __ add(esi, Operand(ebx));
6165 6182
6166 // eax: result string 6183 // eax: result string
6167 // ecx: result length 6184 // ecx: result length
6168 // edx: original value of esi 6185 // edx: original value of esi
6169 // edi: first character of result 6186 // edi: first character of result
6170 // esi: character of sub string start 6187 // esi: character of sub string start
6171 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true); 6188 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true);
6172 __ mov(esi, edx); // Restore esi. 6189 __ mov(esi, edx); // Restore esi.
6173 __ IncrementCounter(&Counters::sub_string_native, 1); 6190 __ IncrementCounter(COUNTERS->sub_string_native(), 1);
6174 __ ret(3 * kPointerSize); 6191 __ ret(3 * kPointerSize);
6175 6192
6176 __ bind(&non_ascii_flat); 6193 __ bind(&non_ascii_flat);
6177 // eax: string 6194 // eax: string
6178 // ebx: instance type & kStringRepresentationMask | kStringEncodingMask 6195 // ebx: instance type & kStringRepresentationMask | kStringEncodingMask
6179 // ecx: result string length 6196 // ecx: result string length
6180 // Check for flat two byte string 6197 // Check for flat two byte string
6181 __ cmp(ebx, kSeqStringTag | kTwoByteStringTag); 6198 __ cmp(ebx, kSeqStringTag | kTwoByteStringTag);
6182 __ j(not_equal, &runtime); 6199 __ j(not_equal, &runtime);
6183 6200
(...skipping 20 matching lines...) Expand all
6204 6221
6205 // eax: result string 6222 // eax: result string
6206 // ecx: result length 6223 // ecx: result length
6207 // edx: original value of esi 6224 // edx: original value of esi
6208 // edi: first character of result 6225 // edi: first character of result
6209 // esi: character of sub string start 6226 // esi: character of sub string start
6210 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false); 6227 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false);
6211 __ mov(esi, edx); // Restore esi. 6228 __ mov(esi, edx); // Restore esi.
6212 6229
6213 __ bind(&return_eax); 6230 __ bind(&return_eax);
6214 __ IncrementCounter(&Counters::sub_string_native, 1); 6231 __ IncrementCounter(COUNTERS->sub_string_native(), 1);
6215 __ ret(3 * kPointerSize); 6232 __ ret(3 * kPointerSize);
6216 6233
6217 // Just jump to runtime to create the sub string. 6234 // Just jump to runtime to create the sub string.
6218 __ bind(&runtime); 6235 __ bind(&runtime);
6219 __ TailCallRuntime(Runtime::kSubString, 3, 1); 6236 __ TailCallRuntime(Runtime::kSubString, 3, 1);
6220 } 6237 }
6221 6238
6222 6239
6223 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 6240 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
6224 Register left, 6241 Register left,
6225 Register right, 6242 Register right,
6226 Register scratch1, 6243 Register scratch1,
6227 Register scratch2, 6244 Register scratch2,
6228 Register scratch3) { 6245 Register scratch3) {
6229 Label result_not_equal; 6246 Label result_not_equal;
6230 Label result_greater; 6247 Label result_greater;
6231 Label compare_lengths; 6248 Label compare_lengths;
6232 6249
6233 __ IncrementCounter(&Counters::string_compare_native, 1); 6250 __ IncrementCounter(COUNTERS->string_compare_native(), 1);
6234 6251
6235 // Find minimum length. 6252 // Find minimum length.
6236 NearLabel left_shorter; 6253 NearLabel left_shorter;
6237 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); 6254 __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
6238 __ mov(scratch3, scratch1); 6255 __ mov(scratch3, scratch1);
6239 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); 6256 __ sub(scratch3, FieldOperand(right, String::kLengthOffset));
6240 6257
6241 Register length_delta = scratch3; 6258 Register length_delta = scratch3;
6242 6259
6243 __ j(less_equal, &left_shorter); 6260 __ j(less_equal, &left_shorter);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
6314 6331
6315 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left 6332 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left
6316 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right 6333 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right
6317 6334
6318 NearLabel not_same; 6335 NearLabel not_same;
6319 __ cmp(edx, Operand(eax)); 6336 __ cmp(edx, Operand(eax));
6320 __ j(not_equal, &not_same); 6337 __ j(not_equal, &not_same);
6321 STATIC_ASSERT(EQUAL == 0); 6338 STATIC_ASSERT(EQUAL == 0);
6322 STATIC_ASSERT(kSmiTag == 0); 6339 STATIC_ASSERT(kSmiTag == 0);
6323 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 6340 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
6324 __ IncrementCounter(&Counters::string_compare_native, 1); 6341 __ IncrementCounter(COUNTERS->string_compare_native(), 1);
6325 __ ret(2 * kPointerSize); 6342 __ ret(2 * kPointerSize);
6326 6343
6327 __ bind(&not_same); 6344 __ bind(&not_same);
6328 6345
6329 // Check that both objects are sequential ascii strings. 6346 // Check that both objects are sequential ascii strings.
6330 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); 6347 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
6331 6348
6332 // Compare flat ascii strings. 6349 // Compare flat ascii strings.
6333 // Drop arguments from the stack. 6350 // Drop arguments from the stack.
6334 __ pop(ecx); 6351 __ pop(ecx);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
6381 __ test(ecx, Immediate(kSmiTagMask)); 6398 __ test(ecx, Immediate(kSmiTagMask));
6382 __ j(zero, &generic_stub, not_taken); 6399 __ j(zero, &generic_stub, not_taken);
6383 6400
6384 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); 6401 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx);
6385 __ j(not_equal, &miss, not_taken); 6402 __ j(not_equal, &miss, not_taken);
6386 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); 6403 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
6387 __ j(not_equal, &miss, not_taken); 6404 __ j(not_equal, &miss, not_taken);
6388 6405
6389 // Inlining the double comparison and falling back to the general compare 6406 // Inlining the double comparison and falling back to the general compare
6390 // stub if NaN is involved or SS2 or CMOV is unsupported. 6407 // stub if NaN is involved or SS2 or CMOV is unsupported.
6391 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { 6408 CpuFeatures* cpu_features = Isolate::Current()->cpu_features();
6409 if (cpu_features->IsSupported(SSE2) && cpu_features->IsSupported(CMOV)) {
6392 CpuFeatures::Scope scope1(SSE2); 6410 CpuFeatures::Scope scope1(SSE2);
6393 CpuFeatures::Scope scope2(CMOV); 6411 CpuFeatures::Scope scope2(CMOV);
6394 6412
6395 // Load left and right operand 6413 // Load left and right operand
6396 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 6414 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
6397 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); 6415 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
6398 6416
6399 // Compare operands 6417 // Compare operands
6400 __ ucomisd(xmm0, xmm1); 6418 __ ucomisd(xmm0, xmm1);
6401 6419
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
6471 __ push(ecx); 6489 __ push(ecx);
6472 6490
6473 // Do a tail call to the rewritten stub. 6491 // Do a tail call to the rewritten stub.
6474 __ jmp(Operand(edi)); 6492 __ jmp(Operand(edi));
6475 } 6493 }
6476 6494
6477 6495
6478 void RecordWriteStub::Generate(MacroAssembler* masm) { 6496 void RecordWriteStub::Generate(MacroAssembler* masm) {
6479 NearLabel skip_incremental_part; 6497 NearLabel skip_incremental_part;
6480 __ jmp(&skip_incremental_part); 6498 __ jmp(&skip_incremental_part);
6481 if (!IncrementalMarking::IsStopped()) { 6499
6500 // TODO(gc) ISOLATES MERGE
6501 // TODO(gc) possible bug, figure out what happens if GC is triggered
6502 // (incremental marking starts) during allocation of code object for this
6503 // stub. Looks like this stub will not be patched.
6504 if (!HEAP->incremental_marking()->IsStopped()) {
6482 ASSERT(masm->get_opcode(-2) == kSkipIncrementalPartInstruction); 6505 ASSERT(masm->get_opcode(-2) == kSkipIncrementalPartInstruction);
6483 masm->set_opcode(-2, kTwoByteNopInstruction); 6506 masm->set_opcode(-2, kTwoByteNopInstruction);
6484 } 6507 }
6485 6508
6486 // If we are also emitting the remembered set code in this stub then we have 6509 // If we are also emitting the remembered set code in this stub then we have
6487 // the object we are writing into in the 'object' register and the slot in 6510 // the object we are writing into in the 'object' register and the slot in
6488 // the 'address' register. We insert a primitive test here to ensure that 6511 // the 'address' register. We insert a primitive test here to ensure that
6489 // this is the case. Otherwise the 'address' register is merely a scratch 6512 // this is the case. Otherwise the 'address' register is merely a scratch
6490 // register. 6513 // register.
6491 if (FLAG_debug_code && emit_remembered_set_ == EMIT_REMEMBERED_SET) { 6514 if (FLAG_debug_code && emit_remembered_set_ == EMIT_REMEMBERED_SET) {
(...skipping 17 matching lines...) Expand all
6509 } 6532 }
6510 __ ret(0); 6533 __ ret(0);
6511 } 6534 }
6512 6535
6513 6536
6514 #undef __ 6537 #undef __
6515 6538
6516 } } // namespace v8::internal 6539 } } // namespace v8::internal
6517 6540
6518 #endif // V8_TARGET_ARCH_IA32 6541 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698