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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 25 matching lines...) Expand all
36 #include "regexp-macro-assembler.h" 36 #include "regexp-macro-assembler.h"
37 37
38 namespace v8 { 38 namespace v8 {
39 namespace internal { 39 namespace internal {
40 40
41 #define __ ACCESS_MASM(masm) 41 #define __ ACCESS_MASM(masm)
42 42
43 void ToNumberStub::Generate(MacroAssembler* masm) { 43 void ToNumberStub::Generate(MacroAssembler* masm) {
44 // The ToNumber stub takes one argument in eax. 44 // The ToNumber stub takes one argument in eax.
45 Label check_heap_number, call_builtin; 45 Label check_heap_number, call_builtin;
46 __ test(eax, Immediate(kSmiTagMask)); 46 __ JumpIfNotSmi(eax, &check_heap_number, Label::kNear);
47 __ j(not_zero, &check_heap_number, Label::kNear);
48 __ ret(0); 47 __ ret(0);
49 48
50 __ bind(&check_heap_number); 49 __ bind(&check_heap_number);
51 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 50 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
52 Factory* factory = masm->isolate()->factory(); 51 Factory* factory = masm->isolate()->factory();
53 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); 52 __ cmp(Operand(ebx), Immediate(factory->heap_number_map()));
54 __ j(not_equal, &call_builtin, Label::kNear); 53 __ j(not_equal, &call_builtin, Label::kNear);
55 __ ret(0); 54 __ ret(0);
56 55
57 __ bind(&call_builtin); 56 __ bind(&call_builtin);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 Label gc; 121 Label gc;
123 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 122 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
124 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, 123 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
125 eax, ebx, ecx, &gc, TAG_OBJECT); 124 eax, ebx, ecx, &gc, TAG_OBJECT);
126 125
127 // Get the function from the stack. 126 // Get the function from the stack.
128 __ mov(ecx, Operand(esp, 1 * kPointerSize)); 127 __ mov(ecx, Operand(esp, 1 * kPointerSize));
129 128
130 // Setup the object header. 129 // Setup the object header.
131 Factory* factory = masm->isolate()->factory(); 130 Factory* factory = masm->isolate()->factory();
132 __ mov(FieldOperand(eax, HeapObject::kMapOffset), factory->context_map()); 131 __ mov(FieldOperand(eax, HeapObject::kMapOffset),
132 factory->function_context_map());
133 __ mov(FieldOperand(eax, Context::kLengthOffset), 133 __ mov(FieldOperand(eax, Context::kLengthOffset),
134 Immediate(Smi::FromInt(length))); 134 Immediate(Smi::FromInt(length)));
135 135
136 // Setup the fixed slots. 136 // Setup the fixed slots.
137 __ Set(ebx, Immediate(0)); // Set to NULL. 137 __ Set(ebx, Immediate(0)); // Set to NULL.
138 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx); 138 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx);
139 __ mov(Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)), eax); 139 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi);
140 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), ebx);
141 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx); 140 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx);
142 141
143 // Copy the global object from the surrounding context. We go through the 142 // Copy the global object from the previous context.
144 // context in the function (ecx) to match the allocation behavior we have 143 __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
145 // in the runtime system (see Heap::AllocateFunctionContext).
146 __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset));
147 __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX)));
148 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); 144 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx);
149 145
150 // Initialize the rest of the slots to undefined. 146 // Initialize the rest of the slots to undefined.
151 __ mov(ebx, factory->undefined_value()); 147 __ mov(ebx, factory->undefined_value());
152 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { 148 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
153 __ mov(Operand(eax, Context::SlotOffset(i)), ebx); 149 __ mov(Operand(eax, Context::SlotOffset(i)), ebx);
154 } 150 }
155 151
156 // Return and remove the on-stack parameter. 152 // Return and remove the on-stack parameter.
157 __ mov(esi, Operand(eax)); 153 __ mov(esi, Operand(eax));
158 __ ret(1 * kPointerSize); 154 __ ret(1 * kPointerSize);
159 155
160 // Need to collect. Call into runtime system. 156 // Need to collect. Call into runtime system.
161 __ bind(&gc); 157 __ bind(&gc);
162 __ TailCallRuntime(Runtime::kNewContext, 1, 1); 158 __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
163 } 159 }
164 160
165 161
166 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { 162 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
167 // Stack layout on entry: 163 // Stack layout on entry:
168 // 164 //
169 // [esp + kPointerSize]: constant elements. 165 // [esp + kPointerSize]: constant elements.
170 // [esp + (2 * kPointerSize)]: literal index. 166 // [esp + (2 * kPointerSize)]: literal index.
171 // [esp + (3 * kPointerSize)]: literals array. 167 // [esp + (3 * kPointerSize)]: literals array.
172 168
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 } 229 }
234 230
235 // Return and remove the on-stack parameters. 231 // Return and remove the on-stack parameters.
236 __ ret(3 * kPointerSize); 232 __ ret(3 * kPointerSize);
237 233
238 __ bind(&slow_case); 234 __ bind(&slow_case);
239 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 235 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
240 } 236 }
241 237
242 238
243 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). 239 // The stub returns zero for false, and a non-zero value for true.
244 void ToBooleanStub::Generate(MacroAssembler* masm) { 240 void ToBooleanStub::Generate(MacroAssembler* masm) {
245 Label false_result, true_result, not_string; 241 Label false_result, true_result, not_string;
242 Factory* factory = masm->isolate()->factory();
243 const Register map = edx;
244
246 __ mov(eax, Operand(esp, 1 * kPointerSize)); 245 __ mov(eax, Operand(esp, 1 * kPointerSize));
247 Factory* factory = masm->isolate()->factory();
248 246
249 // undefined -> false 247 // undefined -> false
250 __ cmp(eax, factory->undefined_value()); 248 __ cmp(eax, factory->undefined_value());
251 __ j(equal, &false_result); 249 __ j(equal, &false_result);
252 250
253 // Boolean -> its value 251 // Boolean -> its value
252 __ cmp(eax, factory->false_value());
253 __ j(equal, &false_result);
254 __ cmp(eax, factory->true_value()); 254 __ cmp(eax, factory->true_value());
255 __ j(equal, &true_result); 255 __ j(equal, &true_result);
256 __ cmp(eax, factory->false_value());
257 __ j(equal, &false_result);
258 256
259 // Smis: 0 -> false, all other -> true 257 // Smis: 0 -> false, all other -> true
260 __ test(eax, Operand(eax)); 258 __ test(eax, Operand(eax));
261 __ j(zero, &false_result); 259 __ j(zero, &false_result);
262 __ test(eax, Immediate(kSmiTagMask)); 260 __ JumpIfSmi(eax, &true_result);
263 __ j(zero, &true_result);
264 261
265 // 'null' => false. 262 // 'null' -> false.
266 __ cmp(eax, factory->null_value()); 263 __ cmp(eax, factory->null_value());
267 __ j(equal, &false_result, Label::kNear); 264 __ j(equal, &false_result, Label::kNear);
268 265
269 // Get the map and type of the heap object. 266 // Get the map of the heap object.
270 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 267 __ mov(map, FieldOperand(eax, HeapObject::kMapOffset));
271 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
272 268
273 // Undetectable => false. 269 // Undetectable -> false.
274 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), 270 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
275 1 << Map::kIsUndetectable); 271 1 << Map::kIsUndetectable);
276 __ j(not_zero, &false_result, Label::kNear); 272 __ j(not_zero, &false_result, Label::kNear);
277 273
278 // JavaScript object => true. 274 // JavaScript object -> true.
279 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE); 275 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
280 __ j(above_equal, &true_result, Label::kNear); 276 __ j(above_equal, &true_result, Label::kNear);
281 277
282 // String value => false iff empty. 278 // String value -> false iff empty.
283 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE); 279 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
284 __ j(above_equal, &not_string, Label::kNear); 280 __ j(above_equal, &not_string, Label::kNear);
285 STATIC_ASSERT(kSmiTag == 0);
286 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0)); 281 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0));
287 __ j(zero, &false_result, Label::kNear); 282 __ j(zero, &false_result, Label::kNear);
288 __ jmp(&true_result, Label::kNear); 283 __ jmp(&true_result, Label::kNear);
289 284
290 __ bind(&not_string); 285 __ bind(&not_string);
291 // HeapNumber => false iff +0, -0, or NaN. 286 // HeapNumber -> false iff +0, -0, or NaN.
292 __ cmp(edx, factory->heap_number_map()); 287 __ cmp(map, factory->heap_number_map());
293 __ j(not_equal, &true_result, Label::kNear); 288 __ j(not_equal, &true_result, Label::kNear);
294 __ fldz(); 289 __ fldz();
295 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 290 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
296 __ FCmp(); 291 __ FCmp();
297 __ j(zero, &false_result, Label::kNear); 292 __ j(zero, &false_result, Label::kNear);
298 // Fall through to |true_result|. 293 // Fall through to |true_result|.
299 294
300 // Return 1/0 for true/false in eax. 295 // Return 1/0 for true/false in tos_.
301 __ bind(&true_result); 296 __ bind(&true_result);
302 __ mov(eax, 1); 297 __ mov(tos_, 1);
303 __ ret(1 * kPointerSize); 298 __ ret(1 * kPointerSize);
304 __ bind(&false_result); 299 __ bind(&false_result);
305 __ mov(eax, 0); 300 __ mov(tos_, 0);
306 __ ret(1 * kPointerSize); 301 __ ret(1 * kPointerSize);
307 } 302 }
308 303
309 304
310 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 305 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
311 // We don't allow a GC during a store buffer overflow so there is no need to 306 // We don't allow a GC during a store buffer overflow so there is no need to
312 // store the registers in any particular way, but we do have to store and 307 // store the registers in any particular way, but we do have to store and
313 // restore them. 308 // restore them.
314 __ pushad(); 309 __ pushad();
315 if (save_doubles_ == kSaveFPRegs) { 310 if (save_doubles_ == kSaveFPRegs) {
(...skipping 19 matching lines...) Expand all
335 } 330 }
336 __ add(Operand(esp), Immediate(kDoubleSize * XMMRegister::kNumRegisters)); 331 __ add(Operand(esp), Immediate(kDoubleSize * XMMRegister::kNumRegisters));
337 } 332 }
338 __ popad(); 333 __ popad();
339 __ ret(0); 334 __ ret(0);
340 } 335 }
341 336
342 337
343 class FloatingPointHelper : public AllStatic { 338 class FloatingPointHelper : public AllStatic {
344 public: 339 public:
345
346 enum ArgLocation { 340 enum ArgLocation {
347 ARGS_ON_STACK, 341 ARGS_ON_STACK,
348 ARGS_IN_REGISTERS 342 ARGS_IN_REGISTERS
349 }; 343 };
350 344
351 // Code pattern for loading a floating point value. Input value must 345 // Code pattern for loading a floating point value. Input value must
352 // be either a smi or a heap number object (fp value). Requirements: 346 // be either a smi or a heap number object (fp value). Requirements:
353 // operand in register number. Returns operand as floating point number 347 // operand in register number. Returns operand as floating point number
354 // on FPU stack. 348 // on FPU stack.
355 static void LoadFloatOperand(MacroAssembler* masm, Register number); 349 static void LoadFloatOperand(MacroAssembler* masm, Register number);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 __ j(greater, &negative, Label::kNear); 537 __ j(greater, &negative, Label::kNear);
544 __ mov(ecx, scratch2); 538 __ mov(ecx, scratch2);
545 __ jmp(&done, Label::kNear); 539 __ jmp(&done, Label::kNear);
546 __ bind(&negative); 540 __ bind(&negative);
547 __ sub(ecx, Operand(scratch2)); 541 __ sub(ecx, Operand(scratch2));
548 __ bind(&done); 542 __ bind(&done);
549 } 543 }
550 } 544 }
551 545
552 546
553 Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
554 UnaryOpStub stub(key, type_info);
555 return stub.GetCode();
556 }
557
558
559 const char* UnaryOpStub::GetName() { 547 const char* UnaryOpStub::GetName() {
560 if (name_ != NULL) return name_; 548 if (name_ != NULL) return name_;
561 const int kMaxNameLength = 100; 549 const int kMaxNameLength = 100;
562 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( 550 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
563 kMaxNameLength); 551 kMaxNameLength);
564 if (name_ == NULL) return "OOM"; 552 if (name_ == NULL) return "OOM";
565 const char* op_name = Token::Name(op_); 553 const char* op_name = Token::Name(op_);
566 const char* overwrite_name = NULL; // Make g++ happy. 554 const char* overwrite_name = NULL; // Make g++ happy.
567 switch (mode_) { 555 switch (mode_) {
568 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; 556 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
(...skipping 23 matching lines...) Expand all
592 break; 580 break;
593 case UnaryOpIC::GENERIC: 581 case UnaryOpIC::GENERIC:
594 GenerateGenericStub(masm); 582 GenerateGenericStub(masm);
595 break; 583 break;
596 } 584 }
597 } 585 }
598 586
599 587
600 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 588 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
601 __ pop(ecx); // Save return address. 589 __ pop(ecx); // Save return address.
602 __ push(eax); 590
603 // the argument is now on top. 591 __ push(eax); // the operand
604 // Push this stub's key. Although the operation and the type info are
605 // encoded into the key, the encoding is opaque, so push them too.
606 __ push(Immediate(Smi::FromInt(MinorKey())));
607 __ push(Immediate(Smi::FromInt(op_))); 592 __ push(Immediate(Smi::FromInt(op_)));
593 __ push(Immediate(Smi::FromInt(mode_)));
608 __ push(Immediate(Smi::FromInt(operand_type_))); 594 __ push(Immediate(Smi::FromInt(operand_type_)));
609 595
610 __ push(ecx); // Push return address. 596 __ push(ecx); // Push return address.
611 597
612 // Patch the caller to an appropriate specialized stub and return the 598 // Patch the caller to an appropriate specialized stub and return the
613 // operation result to the caller of the stub. 599 // operation result to the caller of the stub.
614 __ TailCallExternalReference( 600 __ TailCallExternalReference(
615 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), 601 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
616 masm->isolate()), 4, 1);
617 } 602 }
618 603
619 604
620 // TODO(svenpanne): Use virtual functions instead of switch. 605 // TODO(svenpanne): Use virtual functions instead of switch.
621 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 606 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
622 switch (op_) { 607 switch (op_) {
623 case Token::SUB: 608 case Token::SUB:
624 GenerateSmiStubSub(masm); 609 GenerateSmiStubSub(masm);
625 break; 610 break;
626 case Token::BIT_NOT: 611 case Token::BIT_NOT:
(...skipping 26 matching lines...) Expand all
653 638
654 639
655 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, 640 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
656 Label* non_smi, 641 Label* non_smi,
657 Label* undo, 642 Label* undo,
658 Label* slow, 643 Label* slow,
659 Label::Distance non_smi_near, 644 Label::Distance non_smi_near,
660 Label::Distance undo_near, 645 Label::Distance undo_near,
661 Label::Distance slow_near) { 646 Label::Distance slow_near) {
662 // Check whether the value is a smi. 647 // Check whether the value is a smi.
663 __ test(eax, Immediate(kSmiTagMask)); 648 __ JumpIfNotSmi(eax, non_smi, non_smi_near);
664 __ j(not_zero, non_smi, non_smi_near);
665 649
666 // We can't handle -0 with smis, so use a type transition for that case. 650 // We can't handle -0 with smis, so use a type transition for that case.
667 __ test(eax, Operand(eax)); 651 __ test(eax, Operand(eax));
668 __ j(zero, slow, slow_near); 652 __ j(zero, slow, slow_near);
669 653
670 // Try optimistic subtraction '0 - value', saving operand in eax for undo. 654 // Try optimistic subtraction '0 - value', saving operand in eax for undo.
671 __ mov(edx, Operand(eax)); 655 __ mov(edx, Operand(eax));
672 __ Set(eax, Immediate(0)); 656 __ Set(eax, Immediate(0));
673 __ sub(eax, Operand(edx)); 657 __ sub(eax, Operand(edx));
674 __ j(overflow, undo, undo_near); 658 __ j(overflow, undo, undo_near);
675 __ ret(0); 659 __ ret(0);
676 } 660 }
677 661
678 662
679 void UnaryOpStub::GenerateSmiCodeBitNot( 663 void UnaryOpStub::GenerateSmiCodeBitNot(
680 MacroAssembler* masm, 664 MacroAssembler* masm,
681 Label* non_smi, 665 Label* non_smi,
682 Label::Distance non_smi_near) { 666 Label::Distance non_smi_near) {
683 // Check whether the value is a smi. 667 // Check whether the value is a smi.
684 __ test(eax, Immediate(kSmiTagMask)); 668 __ JumpIfNotSmi(eax, non_smi, non_smi_near);
685 __ j(not_zero, non_smi, non_smi_near);
686 669
687 // Flip bits and revert inverted smi-tag. 670 // Flip bits and revert inverted smi-tag.
688 __ not_(eax); 671 __ not_(eax);
689 __ and_(eax, ~kSmiTagMask); 672 __ and_(eax, ~kSmiTagMask);
690 __ ret(0); 673 __ ret(0);
691 } 674 }
692 675
693 676
694 void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) { 677 void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) {
695 __ mov(eax, Operand(edx)); 678 __ mov(eax, Operand(edx));
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 break; 862 break;
880 case Token::BIT_NOT: 863 case Token::BIT_NOT:
881 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); 864 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
882 break; 865 break;
883 default: 866 default:
884 UNREACHABLE(); 867 UNREACHABLE();
885 } 868 }
886 } 869 }
887 870
888 871
889 Handle<Code> GetBinaryOpStub(int key,
890 BinaryOpIC::TypeInfo type_info,
891 BinaryOpIC::TypeInfo result_type_info) {
892 BinaryOpStub stub(key, type_info, result_type_info);
893 return stub.GetCode();
894 }
895
896
897 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 872 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
898 __ pop(ecx); // Save return address. 873 __ pop(ecx); // Save return address.
899 __ push(edx); 874 __ push(edx);
900 __ push(eax); 875 __ push(eax);
901 // Left and right arguments are now on top. 876 // Left and right arguments are now on top.
902 // Push this stub's key. Although the operation and the type info are 877 // Push this stub's key. Although the operation and the type info are
903 // encoded into the key, the encoding is opaque, so push them too. 878 // encoded into the key, the encoding is opaque, so push them too.
904 __ push(Immediate(Smi::FromInt(MinorKey()))); 879 __ push(Immediate(Smi::FromInt(MinorKey())));
905 __ push(Immediate(Smi::FromInt(op_))); 880 __ push(Immediate(Smi::FromInt(op_)));
906 __ push(Immediate(Smi::FromInt(operands_type_))); 881 __ push(Immediate(Smi::FromInt(operands_type_)));
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 __ or_(right, Operand(left)); 1024 __ or_(right, Operand(left));
1050 combined = right; 1025 combined = right;
1051 break; 1026 break;
1052 1027
1053 default: 1028 default:
1054 break; 1029 break;
1055 } 1030 }
1056 1031
1057 // 3. Perform the smi check of the operands. 1032 // 3. Perform the smi check of the operands.
1058 STATIC_ASSERT(kSmiTag == 0); // Adjust zero check if not the case. 1033 STATIC_ASSERT(kSmiTag == 0); // Adjust zero check if not the case.
1059 __ test(combined, Immediate(kSmiTagMask)); 1034 __ JumpIfNotSmi(combined, &not_smis);
1060 __ j(not_zero, &not_smis);
1061 1035
1062 // 4. Operands are both smis, perform the operation leaving the result in 1036 // 4. Operands are both smis, perform the operation leaving the result in
1063 // eax and check the result if necessary. 1037 // eax and check the result if necessary.
1064 Comment perform_smi(masm, "-- Perform smi operation"); 1038 Comment perform_smi(masm, "-- Perform smi operation");
1065 Label use_fp_on_smis; 1039 Label use_fp_on_smis;
1066 switch (op_) { 1040 switch (op_) {
1067 case Token::BIT_OR: 1041 case Token::BIT_OR:
1068 // Nothing to do. 1042 // Nothing to do.
1069 break; 1043 break;
1070 1044
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING); 1412 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
1439 ASSERT(op_ == Token::ADD); 1413 ASSERT(op_ == Token::ADD);
1440 // If both arguments are strings, call the string add stub. 1414 // If both arguments are strings, call the string add stub.
1441 // Otherwise, do a transition. 1415 // Otherwise, do a transition.
1442 1416
1443 // Registers containing left and right operands respectively. 1417 // Registers containing left and right operands respectively.
1444 Register left = edx; 1418 Register left = edx;
1445 Register right = eax; 1419 Register right = eax;
1446 1420
1447 // Test if left operand is a string. 1421 // Test if left operand is a string.
1448 __ test(left, Immediate(kSmiTagMask)); 1422 __ JumpIfSmi(left, &call_runtime);
1449 __ j(zero, &call_runtime);
1450 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); 1423 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx);
1451 __ j(above_equal, &call_runtime); 1424 __ j(above_equal, &call_runtime);
1452 1425
1453 // Test if right operand is a string. 1426 // Test if right operand is a string.
1454 __ test(right, Immediate(kSmiTagMask)); 1427 __ JumpIfSmi(right, &call_runtime);
1455 __ j(zero, &call_runtime);
1456 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); 1428 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx);
1457 __ j(above_equal, &call_runtime); 1429 __ j(above_equal, &call_runtime);
1458 1430
1459 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); 1431 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
1460 GenerateRegisterArgsPush(masm); 1432 GenerateRegisterArgsPush(masm);
1461 __ TailCallStub(&string_add_stub); 1433 __ TailCallStub(&string_add_stub);
1462 1434
1463 __ bind(&call_runtime); 1435 __ bind(&call_runtime);
1464 GenerateTypeTransition(masm); 1436 GenerateTypeTransition(masm);
1465 } 1437 }
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1581 // Allocate a heap number if needed. 1553 // Allocate a heap number if needed.
1582 __ mov(ebx, Operand(eax)); // ebx: result 1554 __ mov(ebx, Operand(eax)); // ebx: result
1583 Label skip_allocation; 1555 Label skip_allocation;
1584 switch (mode_) { 1556 switch (mode_) {
1585 case OVERWRITE_LEFT: 1557 case OVERWRITE_LEFT:
1586 case OVERWRITE_RIGHT: 1558 case OVERWRITE_RIGHT:
1587 // If the operand was an object, we skip the 1559 // If the operand was an object, we skip the
1588 // allocation of a heap number. 1560 // allocation of a heap number.
1589 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? 1561 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
1590 1 * kPointerSize : 2 * kPointerSize)); 1562 1 * kPointerSize : 2 * kPointerSize));
1591 __ test(eax, Immediate(kSmiTagMask)); 1563 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear);
1592 __ j(not_zero, &skip_allocation, Label::kNear);
1593 // Fall through! 1564 // Fall through!
1594 case NO_OVERWRITE: 1565 case NO_OVERWRITE:
1595 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 1566 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
1596 __ bind(&skip_allocation); 1567 __ bind(&skip_allocation);
1597 break; 1568 break;
1598 default: UNREACHABLE(); 1569 default: UNREACHABLE();
1599 } 1570 }
1600 // Store the result in the HeapNumber and return. 1571 // Store the result in the HeapNumber and return.
1601 if (CpuFeatures::IsSupported(SSE2)) { 1572 if (CpuFeatures::IsSupported(SSE2)) {
1602 CpuFeatures::Scope use_sse2(SSE2); 1573 CpuFeatures::Scope use_sse2(SSE2);
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1796 // Allocate a heap number if needed. 1767 // Allocate a heap number if needed.
1797 __ mov(ebx, Operand(eax)); // ebx: result 1768 __ mov(ebx, Operand(eax)); // ebx: result
1798 Label skip_allocation; 1769 Label skip_allocation;
1799 switch (mode_) { 1770 switch (mode_) {
1800 case OVERWRITE_LEFT: 1771 case OVERWRITE_LEFT:
1801 case OVERWRITE_RIGHT: 1772 case OVERWRITE_RIGHT:
1802 // If the operand was an object, we skip the 1773 // If the operand was an object, we skip the
1803 // allocation of a heap number. 1774 // allocation of a heap number.
1804 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? 1775 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
1805 1 * kPointerSize : 2 * kPointerSize)); 1776 1 * kPointerSize : 2 * kPointerSize));
1806 __ test(eax, Immediate(kSmiTagMask)); 1777 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear);
1807 __ j(not_zero, &skip_allocation, Label::kNear);
1808 // Fall through! 1778 // Fall through!
1809 case NO_OVERWRITE: 1779 case NO_OVERWRITE:
1810 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 1780 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
1811 __ bind(&skip_allocation); 1781 __ bind(&skip_allocation);
1812 break; 1782 break;
1813 default: UNREACHABLE(); 1783 default: UNREACHABLE();
1814 } 1784 }
1815 // Store the result in the HeapNumber and return. 1785 // Store the result in the HeapNumber and return.
1816 if (CpuFeatures::IsSupported(SSE2)) { 1786 if (CpuFeatures::IsSupported(SSE2)) {
1817 CpuFeatures::Scope use_sse2(SSE2); 1787 CpuFeatures::Scope use_sse2(SSE2);
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1996 // Allocate a heap number if needed. 1966 // Allocate a heap number if needed.
1997 __ mov(ebx, Operand(eax)); // ebx: result 1967 __ mov(ebx, Operand(eax)); // ebx: result
1998 Label skip_allocation; 1968 Label skip_allocation;
1999 switch (mode_) { 1969 switch (mode_) {
2000 case OVERWRITE_LEFT: 1970 case OVERWRITE_LEFT:
2001 case OVERWRITE_RIGHT: 1971 case OVERWRITE_RIGHT:
2002 // If the operand was an object, we skip the 1972 // If the operand was an object, we skip the
2003 // allocation of a heap number. 1973 // allocation of a heap number.
2004 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? 1974 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
2005 1 * kPointerSize : 2 * kPointerSize)); 1975 1 * kPointerSize : 2 * kPointerSize));
2006 __ test(eax, Immediate(kSmiTagMask)); 1976 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear);
2007 __ j(not_zero, &skip_allocation, Label::kNear);
2008 // Fall through! 1977 // Fall through!
2009 case NO_OVERWRITE: 1978 case NO_OVERWRITE:
2010 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 1979 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
2011 __ bind(&skip_allocation); 1980 __ bind(&skip_allocation);
2012 break; 1981 break;
2013 default: UNREACHABLE(); 1982 default: UNREACHABLE();
2014 } 1983 }
2015 // Store the result in the HeapNumber and return. 1984 // Store the result in the HeapNumber and return.
2016 if (CpuFeatures::IsSupported(SSE2)) { 1985 if (CpuFeatures::IsSupported(SSE2)) {
2017 CpuFeatures::Scope use_sse2(SSE2); 1986 CpuFeatures::Scope use_sse2(SSE2);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2080 2049
2081 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { 2050 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
2082 ASSERT(op_ == Token::ADD); 2051 ASSERT(op_ == Token::ADD);
2083 Label left_not_string, call_runtime; 2052 Label left_not_string, call_runtime;
2084 2053
2085 // Registers containing left and right operands respectively. 2054 // Registers containing left and right operands respectively.
2086 Register left = edx; 2055 Register left = edx;
2087 Register right = eax; 2056 Register right = eax;
2088 2057
2089 // Test if left operand is a string. 2058 // Test if left operand is a string.
2090 __ test(left, Immediate(kSmiTagMask)); 2059 __ JumpIfSmi(left, &left_not_string, Label::kNear);
2091 __ j(zero, &left_not_string, Label::kNear);
2092 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); 2060 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx);
2093 __ j(above_equal, &left_not_string, Label::kNear); 2061 __ j(above_equal, &left_not_string, Label::kNear);
2094 2062
2095 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); 2063 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
2096 GenerateRegisterArgsPush(masm); 2064 GenerateRegisterArgsPush(masm);
2097 __ TailCallStub(&string_add_left_stub); 2065 __ TailCallStub(&string_add_left_stub);
2098 2066
2099 // Left operand is not a string, test right. 2067 // Left operand is not a string, test right.
2100 __ bind(&left_not_string); 2068 __ bind(&left_not_string);
2101 __ test(right, Immediate(kSmiTagMask)); 2069 __ JumpIfSmi(right, &call_runtime, Label::kNear);
2102 __ j(zero, &call_runtime, Label::kNear);
2103 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); 2070 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx);
2104 __ j(above_equal, &call_runtime, Label::kNear); 2071 __ j(above_equal, &call_runtime, Label::kNear);
2105 2072
2106 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); 2073 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
2107 GenerateRegisterArgsPush(masm); 2074 GenerateRegisterArgsPush(masm);
2108 __ TailCallStub(&string_add_right_stub); 2075 __ TailCallStub(&string_add_right_stub);
2109 2076
2110 // Neither argument is a string. 2077 // Neither argument is a string.
2111 __ bind(&call_runtime); 2078 __ bind(&call_runtime);
2112 } 2079 }
2113 2080
2114 2081
2115 void BinaryOpStub::GenerateHeapResultAllocation( 2082 void BinaryOpStub::GenerateHeapResultAllocation(
2116 MacroAssembler* masm, 2083 MacroAssembler* masm,
2117 Label* alloc_failure) { 2084 Label* alloc_failure) {
2118 Label skip_allocation; 2085 Label skip_allocation;
2119 OverwriteMode mode = mode_; 2086 OverwriteMode mode = mode_;
2120 switch (mode) { 2087 switch (mode) {
2121 case OVERWRITE_LEFT: { 2088 case OVERWRITE_LEFT: {
2122 // If the argument in edx is already an object, we skip the 2089 // If the argument in edx is already an object, we skip the
2123 // allocation of a heap number. 2090 // allocation of a heap number.
2124 __ test(edx, Immediate(kSmiTagMask)); 2091 __ JumpIfNotSmi(edx, &skip_allocation, Label::kNear);
2125 __ j(not_zero, &skip_allocation);
2126 // Allocate a heap number for the result. Keep eax and edx intact 2092 // Allocate a heap number for the result. Keep eax and edx intact
2127 // for the possible runtime call. 2093 // for the possible runtime call.
2128 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); 2094 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure);
2129 // Now edx can be overwritten losing one of the arguments as we are 2095 // Now edx can be overwritten losing one of the arguments as we are
2130 // now done and will not need it any more. 2096 // now done and will not need it any more.
2131 __ mov(edx, Operand(ebx)); 2097 __ mov(edx, Operand(ebx));
2132 __ bind(&skip_allocation); 2098 __ bind(&skip_allocation);
2133 // Use object in edx as a result holder 2099 // Use object in edx as a result holder
2134 __ mov(eax, Operand(edx)); 2100 __ mov(eax, Operand(edx));
2135 break; 2101 break;
2136 } 2102 }
2137 case OVERWRITE_RIGHT: 2103 case OVERWRITE_RIGHT:
2138 // If the argument in eax is already an object, we skip the 2104 // If the argument in eax is already an object, we skip the
2139 // allocation of a heap number. 2105 // allocation of a heap number.
2140 __ test(eax, Immediate(kSmiTagMask)); 2106 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear);
2141 __ j(not_zero, &skip_allocation);
2142 // Fall through! 2107 // Fall through!
2143 case NO_OVERWRITE: 2108 case NO_OVERWRITE:
2144 // Allocate a heap number for the result. Keep eax and edx intact 2109 // Allocate a heap number for the result. Keep eax and edx intact
2145 // for the possible runtime call. 2110 // for the possible runtime call.
2146 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); 2111 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure);
2147 // Now eax can be overwritten losing one of the arguments as we are 2112 // Now eax can be overwritten losing one of the arguments as we are
2148 // now done and will not need it any more. 2113 // now done and will not need it any more.
2149 __ mov(eax, ebx); 2114 __ mov(eax, ebx);
2150 __ bind(&skip_allocation); 2115 __ bind(&skip_allocation);
2151 break; 2116 break;
(...skipping 26 matching lines...) Expand all
2178 2143
2179 Label runtime_call; 2144 Label runtime_call;
2180 Label runtime_call_clear_stack; 2145 Label runtime_call_clear_stack;
2181 Label skip_cache; 2146 Label skip_cache;
2182 const bool tagged = (argument_type_ == TAGGED); 2147 const bool tagged = (argument_type_ == TAGGED);
2183 if (tagged) { 2148 if (tagged) {
2184 // Test that eax is a number. 2149 // Test that eax is a number.
2185 Label input_not_smi; 2150 Label input_not_smi;
2186 Label loaded; 2151 Label loaded;
2187 __ mov(eax, Operand(esp, kPointerSize)); 2152 __ mov(eax, Operand(esp, kPointerSize));
2188 __ test(eax, Immediate(kSmiTagMask)); 2153 __ JumpIfNotSmi(eax, &input_not_smi, Label::kNear);
2189 __ j(not_zero, &input_not_smi, Label::kNear);
2190 // Input is a smi. Untag and load it onto the FPU stack. 2154 // Input is a smi. Untag and load it onto the FPU stack.
2191 // Then load the low and high words of the double into ebx, edx. 2155 // Then load the low and high words of the double into ebx, edx.
2192 STATIC_ASSERT(kSmiTagSize == 1); 2156 STATIC_ASSERT(kSmiTagSize == 1);
2193 __ sar(eax, 1); 2157 __ sar(eax, 1);
2194 __ sub(Operand(esp), Immediate(2 * kPointerSize)); 2158 __ sub(Operand(esp), Immediate(2 * kPointerSize));
2195 __ mov(Operand(esp, 0), eax); 2159 __ mov(Operand(esp, 0), eax);
2196 __ fild_s(Operand(esp, 0)); 2160 __ fild_s(Operand(esp, 0));
2197 __ fst_d(Operand(esp, 0)); 2161 __ fst_d(Operand(esp, 0));
2198 __ pop(edx); 2162 __ pop(edx);
2199 __ pop(ebx); 2163 __ pop(ebx);
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
2457 // Output: eax, ecx are left and right integers for a bit op. 2421 // Output: eax, ecx are left and right integers for a bit op.
2458 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, 2422 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm,
2459 bool use_sse3, 2423 bool use_sse3,
2460 Label* conversion_failure) { 2424 Label* conversion_failure) {
2461 // Check float operands. 2425 // Check float operands.
2462 Label arg1_is_object, check_undefined_arg1; 2426 Label arg1_is_object, check_undefined_arg1;
2463 Label arg2_is_object, check_undefined_arg2; 2427 Label arg2_is_object, check_undefined_arg2;
2464 Label load_arg2, done; 2428 Label load_arg2, done;
2465 2429
2466 // Test if arg1 is a Smi. 2430 // Test if arg1 is a Smi.
2467 __ test(edx, Immediate(kSmiTagMask)); 2431 __ JumpIfNotSmi(edx, &arg1_is_object);
2468 __ j(not_zero, &arg1_is_object);
2469 2432
2470 __ SmiUntag(edx); 2433 __ SmiUntag(edx);
2471 __ jmp(&load_arg2); 2434 __ jmp(&load_arg2);
2472 2435
2473 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 2436 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
2474 __ bind(&check_undefined_arg1); 2437 __ bind(&check_undefined_arg1);
2475 Factory* factory = masm->isolate()->factory(); 2438 Factory* factory = masm->isolate()->factory();
2476 __ cmp(edx, factory->undefined_value()); 2439 __ cmp(edx, factory->undefined_value());
2477 __ j(not_equal, conversion_failure); 2440 __ j(not_equal, conversion_failure);
2478 __ mov(edx, Immediate(0)); 2441 __ mov(edx, Immediate(0));
2479 __ jmp(&load_arg2); 2442 __ jmp(&load_arg2);
2480 2443
2481 __ bind(&arg1_is_object); 2444 __ bind(&arg1_is_object);
2482 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 2445 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
2483 __ cmp(ebx, factory->heap_number_map()); 2446 __ cmp(ebx, factory->heap_number_map());
2484 __ j(not_equal, &check_undefined_arg1); 2447 __ j(not_equal, &check_undefined_arg1);
2485 2448
2486 // Get the untagged integer version of the edx heap number in ecx. 2449 // Get the untagged integer version of the edx heap number in ecx.
2487 IntegerConvert(masm, edx, use_sse3, conversion_failure); 2450 IntegerConvert(masm, edx, use_sse3, conversion_failure);
2488 __ mov(edx, ecx); 2451 __ mov(edx, ecx);
2489 2452
2490 // Here edx has the untagged integer, eax has a Smi or a heap number. 2453 // Here edx has the untagged integer, eax has a Smi or a heap number.
2491 __ bind(&load_arg2); 2454 __ bind(&load_arg2);
2492 2455
2493 // Test if arg2 is a Smi. 2456 // Test if arg2 is a Smi.
2494 __ test(eax, Immediate(kSmiTagMask)); 2457 __ JumpIfNotSmi(eax, &arg2_is_object);
2495 __ j(not_zero, &arg2_is_object);
2496 2458
2497 __ SmiUntag(eax); 2459 __ SmiUntag(eax);
2498 __ mov(ecx, eax); 2460 __ mov(ecx, eax);
2499 __ jmp(&done); 2461 __ jmp(&done);
2500 2462
2501 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 2463 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
2502 __ bind(&check_undefined_arg2); 2464 __ bind(&check_undefined_arg2);
2503 __ cmp(eax, factory->undefined_value()); 2465 __ cmp(eax, factory->undefined_value());
2504 __ j(not_equal, conversion_failure); 2466 __ j(not_equal, conversion_failure);
2505 __ mov(ecx, Immediate(0)); 2467 __ mov(ecx, Immediate(0));
(...skipping 15 matching lines...) Expand all
2521 bool use_sse3, 2483 bool use_sse3,
2522 Label* not_int32) { 2484 Label* not_int32) {
2523 return; 2485 return;
2524 } 2486 }
2525 2487
2526 2488
2527 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, 2489 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
2528 Register number) { 2490 Register number) {
2529 Label load_smi, done; 2491 Label load_smi, done;
2530 2492
2531 __ test(number, Immediate(kSmiTagMask)); 2493 __ JumpIfSmi(number, &load_smi, Label::kNear);
2532 __ j(zero, &load_smi, Label::kNear);
2533 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); 2494 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset));
2534 __ jmp(&done, Label::kNear); 2495 __ jmp(&done, Label::kNear);
2535 2496
2536 __ bind(&load_smi); 2497 __ bind(&load_smi);
2537 __ SmiUntag(number); 2498 __ SmiUntag(number);
2538 __ push(number); 2499 __ push(number);
2539 __ fild_s(Operand(esp, 0)); 2500 __ fild_s(Operand(esp, 0));
2540 __ pop(number); 2501 __ pop(number);
2541 2502
2542 __ bind(&done); 2503 __ bind(&done);
2543 } 2504 }
2544 2505
2545 2506
2546 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) { 2507 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) {
2547 Label load_smi_edx, load_eax, load_smi_eax, done; 2508 Label load_smi_edx, load_eax, load_smi_eax, done;
2548 // Load operand in edx into xmm0. 2509 // Load operand in edx into xmm0.
2549 __ test(edx, Immediate(kSmiTagMask)); 2510 __ JumpIfSmi(edx, &load_smi_edx, Label::kNear);
2550 // Argument in edx is a smi.
2551 __ j(zero, &load_smi_edx, Label::kNear);
2552 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 2511 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
2553 2512
2554 __ bind(&load_eax); 2513 __ bind(&load_eax);
2555 // Load operand in eax into xmm1. 2514 // Load operand in eax into xmm1.
2556 __ test(eax, Immediate(kSmiTagMask)); 2515 __ JumpIfSmi(eax, &load_smi_eax, Label::kNear);
2557 // Argument in eax is a smi.
2558 __ j(zero, &load_smi_eax, Label::kNear);
2559 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); 2516 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2560 __ jmp(&done, Label::kNear); 2517 __ jmp(&done, Label::kNear);
2561 2518
2562 __ bind(&load_smi_edx); 2519 __ bind(&load_smi_edx);
2563 __ SmiUntag(edx); // Untag smi before converting to float. 2520 __ SmiUntag(edx); // Untag smi before converting to float.
2564 __ cvtsi2sd(xmm0, Operand(edx)); 2521 __ cvtsi2sd(xmm0, Operand(edx));
2565 __ SmiTag(edx); // Retag smi for heap number overwriting test. 2522 __ SmiTag(edx); // Retag smi for heap number overwriting test.
2566 __ jmp(&load_eax); 2523 __ jmp(&load_eax);
2567 2524
2568 __ bind(&load_smi_eax); 2525 __ bind(&load_smi_eax);
2569 __ SmiUntag(eax); // Untag smi before converting to float. 2526 __ SmiUntag(eax); // Untag smi before converting to float.
2570 __ cvtsi2sd(xmm1, Operand(eax)); 2527 __ cvtsi2sd(xmm1, Operand(eax));
2571 __ SmiTag(eax); // Retag smi for heap number overwriting test. 2528 __ SmiTag(eax); // Retag smi for heap number overwriting test.
2572 2529
2573 __ bind(&done); 2530 __ bind(&done);
2574 } 2531 }
2575 2532
2576 2533
2577 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, 2534 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm,
2578 Label* not_numbers) { 2535 Label* not_numbers) {
2579 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; 2536 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
2580 // Load operand in edx into xmm0, or branch to not_numbers. 2537 // Load operand in edx into xmm0, or branch to not_numbers.
2581 __ test(edx, Immediate(kSmiTagMask)); 2538 __ JumpIfSmi(edx, &load_smi_edx, Label::kNear);
2582 // Argument in edx is a smi.
2583 __ j(zero, &load_smi_edx, Label::kNear);
2584 Factory* factory = masm->isolate()->factory(); 2539 Factory* factory = masm->isolate()->factory();
2585 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); 2540 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map());
2586 __ j(not_equal, not_numbers); // Argument in edx is not a number. 2541 __ j(not_equal, not_numbers); // Argument in edx is not a number.
2587 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 2542 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
2588 __ bind(&load_eax); 2543 __ bind(&load_eax);
2589 // Load operand in eax into xmm1, or branch to not_numbers. 2544 // Load operand in eax into xmm1, or branch to not_numbers.
2590 __ test(eax, Immediate(kSmiTagMask)); 2545 __ JumpIfSmi(eax, &load_smi_eax, Label::kNear);
2591 // Argument in eax is a smi.
2592 __ j(zero, &load_smi_eax, Label::kNear);
2593 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); 2546 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map());
2594 __ j(equal, &load_float_eax, Label::kNear); 2547 __ j(equal, &load_float_eax, Label::kNear);
2595 __ jmp(not_numbers); // Argument in eax is not a number. 2548 __ jmp(not_numbers); // Argument in eax is not a number.
2596 __ bind(&load_smi_edx); 2549 __ bind(&load_smi_edx);
2597 __ SmiUntag(edx); // Untag smi before converting to float. 2550 __ SmiUntag(edx); // Untag smi before converting to float.
2598 __ cvtsi2sd(xmm0, Operand(edx)); 2551 __ cvtsi2sd(xmm0, Operand(edx));
2599 __ SmiTag(edx); // Retag smi for heap number overwriting test. 2552 __ SmiTag(edx); // Retag smi for heap number overwriting test.
2600 __ jmp(&load_eax); 2553 __ jmp(&load_eax);
2601 __ bind(&load_smi_eax); 2554 __ bind(&load_smi_eax);
2602 __ SmiUntag(eax); // Untag smi before converting to float. 2555 __ SmiUntag(eax); // Untag smi before converting to float.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2642 2595
2643 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, 2596 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
2644 Register scratch, 2597 Register scratch,
2645 ArgLocation arg_location) { 2598 ArgLocation arg_location) {
2646 Label load_smi_1, load_smi_2, done_load_1, done; 2599 Label load_smi_1, load_smi_2, done_load_1, done;
2647 if (arg_location == ARGS_IN_REGISTERS) { 2600 if (arg_location == ARGS_IN_REGISTERS) {
2648 __ mov(scratch, edx); 2601 __ mov(scratch, edx);
2649 } else { 2602 } else {
2650 __ mov(scratch, Operand(esp, 2 * kPointerSize)); 2603 __ mov(scratch, Operand(esp, 2 * kPointerSize));
2651 } 2604 }
2652 __ test(scratch, Immediate(kSmiTagMask)); 2605 __ JumpIfSmi(scratch, &load_smi_1, Label::kNear);
2653 __ j(zero, &load_smi_1, Label::kNear);
2654 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); 2606 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
2655 __ bind(&done_load_1); 2607 __ bind(&done_load_1);
2656 2608
2657 if (arg_location == ARGS_IN_REGISTERS) { 2609 if (arg_location == ARGS_IN_REGISTERS) {
2658 __ mov(scratch, eax); 2610 __ mov(scratch, eax);
2659 } else { 2611 } else {
2660 __ mov(scratch, Operand(esp, 1 * kPointerSize)); 2612 __ mov(scratch, Operand(esp, 1 * kPointerSize));
2661 } 2613 }
2662 __ test(scratch, Immediate(kSmiTagMask)); 2614 __ JumpIfSmi(scratch, &load_smi_2, Label::kNear);
2663 __ j(zero, &load_smi_2, Label::kNear);
2664 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); 2615 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
2665 __ jmp(&done, Label::kNear); 2616 __ jmp(&done, Label::kNear);
2666 2617
2667 __ bind(&load_smi_1); 2618 __ bind(&load_smi_1);
2668 __ SmiUntag(scratch); 2619 __ SmiUntag(scratch);
2669 __ push(scratch); 2620 __ push(scratch);
2670 __ fild_s(Operand(esp, 0)); 2621 __ fild_s(Operand(esp, 0));
2671 __ pop(scratch); 2622 __ pop(scratch);
2672 __ jmp(&done_load_1); 2623 __ jmp(&done_load_1);
2673 2624
(...skipping 24 matching lines...) Expand all
2698 __ pop(scratch); 2649 __ pop(scratch);
2699 } 2650 }
2700 2651
2701 2652
2702 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, 2653 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
2703 Label* non_float, 2654 Label* non_float,
2704 Register scratch) { 2655 Register scratch) {
2705 Label test_other, done; 2656 Label test_other, done;
2706 // Test if both operands are floats or smi -> scratch=k_is_float; 2657 // Test if both operands are floats or smi -> scratch=k_is_float;
2707 // Otherwise scratch = k_not_float. 2658 // Otherwise scratch = k_not_float.
2708 __ test(edx, Immediate(kSmiTagMask)); 2659 __ JumpIfSmi(edx, &test_other, Label::kNear);
2709 __ j(zero, &test_other, Label::kNear); // argument in edx is OK
2710 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); 2660 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset));
2711 Factory* factory = masm->isolate()->factory(); 2661 Factory* factory = masm->isolate()->factory();
2712 __ cmp(scratch, factory->heap_number_map()); 2662 __ cmp(scratch, factory->heap_number_map());
2713 __ j(not_equal, non_float); // argument in edx is not a number -> NaN 2663 __ j(not_equal, non_float); // argument in edx is not a number -> NaN
2714 2664
2715 __ bind(&test_other); 2665 __ bind(&test_other);
2716 __ test(eax, Immediate(kSmiTagMask)); 2666 __ JumpIfSmi(eax, &done, Label::kNear);
2717 __ j(zero, &done, Label::kNear); // argument in eax is OK
2718 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); 2667 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset));
2719 __ cmp(scratch, factory->heap_number_map()); 2668 __ cmp(scratch, factory->heap_number_map());
2720 __ j(not_equal, non_float); // argument in eax is not a number -> NaN 2669 __ j(not_equal, non_float); // argument in eax is not a number -> NaN
2721 2670
2722 // Fall-through: Both operands are numbers. 2671 // Fall-through: Both operands are numbers.
2723 __ bind(&done); 2672 __ bind(&done);
2724 } 2673 }
2725 2674
2726 2675
2727 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, 2676 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm,
(...skipping 15 matching lines...) Expand all
2743 __ mov(edx, Operand(esp, 2 * kPointerSize)); 2692 __ mov(edx, Operand(esp, 2 * kPointerSize));
2744 __ mov(eax, Operand(esp, 1 * kPointerSize)); 2693 __ mov(eax, Operand(esp, 1 * kPointerSize));
2745 2694
2746 // Save 1 in xmm3 - we need this several times later on. 2695 // Save 1 in xmm3 - we need this several times later on.
2747 __ mov(ecx, Immediate(1)); 2696 __ mov(ecx, Immediate(1));
2748 __ cvtsi2sd(xmm3, Operand(ecx)); 2697 __ cvtsi2sd(xmm3, Operand(ecx));
2749 2698
2750 Label exponent_nonsmi; 2699 Label exponent_nonsmi;
2751 Label base_nonsmi; 2700 Label base_nonsmi;
2752 // If the exponent is a heap number go to that specific case. 2701 // If the exponent is a heap number go to that specific case.
2753 __ test(eax, Immediate(kSmiTagMask)); 2702 __ JumpIfNotSmi(eax, &exponent_nonsmi);
2754 __ j(not_zero, &exponent_nonsmi); 2703 __ JumpIfNotSmi(edx, &base_nonsmi);
2755 __ test(edx, Immediate(kSmiTagMask));
2756 __ j(not_zero, &base_nonsmi);
2757 2704
2758 // Optimized version when both exponent and base are smis. 2705 // Optimized version when both exponent and base are smis.
2759 Label powi; 2706 Label powi;
2760 __ SmiUntag(edx); 2707 __ SmiUntag(edx);
2761 __ cvtsi2sd(xmm0, Operand(edx)); 2708 __ cvtsi2sd(xmm0, Operand(edx));
2762 __ jmp(&powi); 2709 __ jmp(&powi);
2763 // exponent is smi and base is a heapnumber. 2710 // exponent is smi and base is a heapnumber.
2764 __ bind(&base_nonsmi); 2711 __ bind(&base_nonsmi);
2765 Factory* factory = masm->isolate()->factory(); 2712 Factory* factory = masm->isolate()->factory();
2766 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2713 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2818 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 2765 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
2819 factory->heap_number_map()); 2766 factory->heap_number_map());
2820 __ j(not_equal, &call_runtime); 2767 __ j(not_equal, &call_runtime);
2821 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); 2768 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2822 // Test if exponent is nan. 2769 // Test if exponent is nan.
2823 __ ucomisd(xmm1, xmm1); 2770 __ ucomisd(xmm1, xmm1);
2824 __ j(parity_even, &call_runtime); 2771 __ j(parity_even, &call_runtime);
2825 2772
2826 Label base_not_smi; 2773 Label base_not_smi;
2827 Label handle_special_cases; 2774 Label handle_special_cases;
2828 __ test(edx, Immediate(kSmiTagMask)); 2775 __ JumpIfNotSmi(edx, &base_not_smi, Label::kNear);
2829 __ j(not_zero, &base_not_smi, Label::kNear);
2830 __ SmiUntag(edx); 2776 __ SmiUntag(edx);
2831 __ cvtsi2sd(xmm0, Operand(edx)); 2777 __ cvtsi2sd(xmm0, Operand(edx));
2832 __ jmp(&handle_special_cases, Label::kNear); 2778 __ jmp(&handle_special_cases, Label::kNear);
2833 2779
2834 __ bind(&base_not_smi); 2780 __ bind(&base_not_smi);
2835 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2781 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2836 factory->heap_number_map()); 2782 factory->heap_number_map());
2837 __ j(not_equal, &call_runtime); 2783 __ j(not_equal, &call_runtime);
2838 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); 2784 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset));
2839 __ and_(ecx, HeapNumber::kExponentMask); 2785 __ and_(ecx, HeapNumber::kExponentMask);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2891 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 2837 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
2892 // The key is in edx and the parameter count is in eax. 2838 // The key is in edx and the parameter count is in eax.
2893 2839
2894 // The displacement is used for skipping the frame pointer on the 2840 // The displacement is used for skipping the frame pointer on the
2895 // stack. It is the offset of the last parameter (if any) relative 2841 // stack. It is the offset of the last parameter (if any) relative
2896 // to the frame pointer. 2842 // to the frame pointer.
2897 static const int kDisplacement = 1 * kPointerSize; 2843 static const int kDisplacement = 1 * kPointerSize;
2898 2844
2899 // Check that the key is a smi. 2845 // Check that the key is a smi.
2900 Label slow; 2846 Label slow;
2901 __ test(edx, Immediate(kSmiTagMask)); 2847 __ JumpIfNotSmi(edx, &slow);
2902 __ j(not_zero, &slow);
2903 2848
2904 // Check if the calling frame is an arguments adaptor frame. 2849 // Check if the calling frame is an arguments adaptor frame.
2905 Label adaptor; 2850 Label adaptor;
2906 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2851 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2907 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); 2852 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset));
2908 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2853 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2909 __ j(equal, &adaptor, Label::kNear); 2854 __ j(equal, &adaptor, Label::kNear);
2910 2855
2911 // Check index against formal parameters count limit passed in 2856 // Check index against formal parameters count limit passed in
2912 // through register eax. Use unsigned comparison to get negative 2857 // through register eax. Use unsigned comparison to get negative
(...skipping 28 matching lines...) Expand all
2941 // Slow-case: Handle non-smi or out-of-bounds access to arguments 2886 // Slow-case: Handle non-smi or out-of-bounds access to arguments
2942 // by calling the runtime system. 2887 // by calling the runtime system.
2943 __ bind(&slow); 2888 __ bind(&slow);
2944 __ pop(ebx); // Return address. 2889 __ pop(ebx); // Return address.
2945 __ push(edx); 2890 __ push(edx);
2946 __ push(ebx); 2891 __ push(ebx);
2947 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 2892 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
2948 } 2893 }
2949 2894
2950 2895
2951 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { 2896 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
2952 // esp[0] : return address 2897 // esp[0] : return address
2953 // esp[4] : number of parameters 2898 // esp[4] : number of parameters
2954 // esp[8] : receiver displacement 2899 // esp[8] : receiver displacement
2955 // esp[16] : function 2900 // esp[12] : function
2956 2901
2957 // The displacement is used for skipping the return address and the 2902 // Check if the calling frame is an arguments adaptor frame.
2958 // frame pointer on the stack. It is the offset of the last 2903 Label runtime;
2959 // parameter (if any) relative to the frame pointer. 2904 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2960 static const int kDisplacement = 2 * kPointerSize; 2905 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
2906 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2907 __ j(not_equal, &runtime, Label::kNear);
2908
2909 // Patch the arguments.length and the parameters pointer.
2910 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2911 __ mov(Operand(esp, 1 * kPointerSize), ecx);
2912 __ lea(edx, Operand(edx, ecx, times_2,
2913 StandardFrameConstants::kCallerSPOffset));
2914 __ mov(Operand(esp, 2 * kPointerSize), edx);
2915
2916 __ bind(&runtime);
2917 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
2918 }
2919
2920
2921 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
2922 // esp[0] : return address
2923 // esp[4] : number of parameters (tagged)
2924 // esp[8] : receiver displacement
2925 // esp[12] : function
2926
2927 // ebx = parameter count (tagged)
2928 __ mov(ebx, Operand(esp, 1 * kPointerSize));
2929
2930 // Check if the calling frame is an arguments adaptor frame.
2931 // TODO(rossberg): Factor out some of the bits that are shared with the other
2932 // Generate* functions.
2933 Label runtime;
2934 Label adaptor_frame, try_allocate;
2935 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2936 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
2937 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2938 __ j(equal, &adaptor_frame, Label::kNear);
2939
2940 // No adaptor, parameter count = argument count.
2941 __ mov(ecx, ebx);
2942 __ jmp(&try_allocate, Label::kNear);
2943
2944 // We have an adaptor frame. Patch the parameters pointer.
2945 __ bind(&adaptor_frame);
2946 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2947 __ lea(edx, Operand(edx, ecx, times_2,
2948 StandardFrameConstants::kCallerSPOffset));
2949 __ mov(Operand(esp, 2 * kPointerSize), edx);
2950
2951 // ebx = parameter count (tagged)
2952 // ecx = argument count (tagged)
2953 // esp[4] = parameter count (tagged)
2954 // esp[8] = address of receiver argument
2955 // Compute the mapped parameter count = min(ebx, ecx) in ebx.
2956 __ cmp(ebx, Operand(ecx));
2957 __ j(less_equal, &try_allocate, Label::kNear);
2958 __ mov(ebx, ecx);
2959
2960 __ bind(&try_allocate);
2961
2962 // Save mapped parameter count.
2963 __ push(ebx);
2964
2965 // Compute the sizes of backing store, parameter map, and arguments object.
2966 // 1. Parameter map, has 2 extra words containing context and backing store.
2967 const int kParameterMapHeaderSize =
2968 FixedArray::kHeaderSize + 2 * kPointerSize;
2969 Label no_parameter_map;
2970 __ test(ebx, Operand(ebx));
2971 __ j(zero, &no_parameter_map, Label::kNear);
2972 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize));
2973 __ bind(&no_parameter_map);
2974
2975 // 2. Backing store.
2976 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
2977
2978 // 3. Arguments object.
2979 __ add(Operand(ebx), Immediate(Heap::kArgumentsObjectSize));
2980
2981 // Do the allocation of all three objects in one go.
2982 __ AllocateInNewSpace(ebx, eax, edx, edi, &runtime, TAG_OBJECT);
2983
2984 // eax = address of new object(s) (tagged)
2985 // ecx = argument count (tagged)
2986 // esp[0] = mapped parameter count (tagged)
2987 // esp[8] = parameter count (tagged)
2988 // esp[12] = address of receiver argument
2989 // Get the arguments boilerplate from the current (global) context into edi.
2990 Label has_mapped_parameters, copy;
2991 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2992 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset));
2993 __ mov(ebx, Operand(esp, 0 * kPointerSize));
2994 __ test(ebx, Operand(ebx));
2995 __ j(not_zero, &has_mapped_parameters, Label::kNear);
2996 __ mov(edi, Operand(edi,
2997 Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX)));
2998 __ jmp(&copy, Label::kNear);
2999
3000 __ bind(&has_mapped_parameters);
3001 __ mov(edi, Operand(edi,
3002 Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX)));
3003 __ bind(&copy);
3004
3005 // eax = address of new object (tagged)
3006 // ebx = mapped parameter count (tagged)
3007 // ecx = argument count (tagged)
3008 // edi = address of boilerplate object (tagged)
3009 // esp[0] = mapped parameter count (tagged)
3010 // esp[8] = parameter count (tagged)
3011 // esp[12] = address of receiver argument
3012 // Copy the JS object part.
3013 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
3014 __ mov(edx, FieldOperand(edi, i));
3015 __ mov(FieldOperand(eax, i), edx);
3016 }
3017
3018 // Setup the callee in-object property.
3019 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
3020 __ mov(edx, Operand(esp, 4 * kPointerSize));
3021 __ mov(FieldOperand(eax, JSObject::kHeaderSize +
3022 Heap::kArgumentsCalleeIndex * kPointerSize),
3023 edx);
3024
3025 // Use the length (smi tagged) and set that as an in-object property too.
3026 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
3027 __ mov(FieldOperand(eax, JSObject::kHeaderSize +
3028 Heap::kArgumentsLengthIndex * kPointerSize),
3029 ecx);
3030
3031 // Setup the elements pointer in the allocated arguments object.
3032 // If we allocated a parameter map, edi will point there, otherwise to the
3033 // backing store.
3034 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize));
3035 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
3036
3037 // eax = address of new object (tagged)
3038 // ebx = mapped parameter count (tagged)
3039 // ecx = argument count (tagged)
3040 // edi = address of parameter map or backing store (tagged)
3041 // esp[0] = mapped parameter count (tagged)
3042 // esp[8] = parameter count (tagged)
3043 // esp[12] = address of receiver argument
3044 // Free a register.
3045 __ push(eax);
3046
3047 // Initialize parameter map. If there are no mapped arguments, we're done.
3048 Label skip_parameter_map;
3049 __ test(ebx, Operand(ebx));
3050 __ j(zero, &skip_parameter_map);
3051
3052 __ mov(FieldOperand(edi, FixedArray::kMapOffset),
3053 Immediate(FACTORY->non_strict_arguments_elements_map()));
3054 __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2))));
3055 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax);
3056 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi);
3057 __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize));
3058 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax);
3059
3060 // Copy the parameter slots and the holes in the arguments.
3061 // We need to fill in mapped_parameter_count slots. They index the context,
3062 // where parameters are stored in reverse order, at
3063 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
3064 // The mapped parameter thus need to get indices
3065 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
3066 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
3067 // We loop from right to left.
3068 Label parameters_loop, parameters_test;
3069 __ push(ecx);
3070 __ mov(eax, Operand(esp, 2 * kPointerSize));
3071 __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
3072 __ add(ebx, Operand(esp, 4 * kPointerSize));
3073 __ sub(ebx, Operand(eax));
3074 __ mov(ecx, FACTORY->the_hole_value());
3075 __ mov(edx, edi);
3076 __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize));
3077 // eax = loop variable (tagged)
3078 // ebx = mapping index (tagged)
3079 // ecx = the hole value
3080 // edx = address of parameter map (tagged)
3081 // edi = address of backing store (tagged)
3082 // esp[0] = argument count (tagged)
3083 // esp[4] = address of new object (tagged)
3084 // esp[8] = mapped parameter count (tagged)
3085 // esp[16] = parameter count (tagged)
3086 // esp[20] = address of receiver argument
3087 __ jmp(&parameters_test, Label::kNear);
3088
3089 __ bind(&parameters_loop);
3090 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3091 __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx);
3092 __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx);
3093 __ add(Operand(ebx), Immediate(Smi::FromInt(1)));
3094 __ bind(&parameters_test);
3095 __ test(eax, Operand(eax));
3096 __ j(not_zero, &parameters_loop, Label::kNear);
3097 __ pop(ecx);
3098
3099 __ bind(&skip_parameter_map);
3100
3101 // ecx = argument count (tagged)
3102 // edi = address of backing store (tagged)
3103 // esp[0] = address of new object (tagged)
3104 // esp[4] = mapped parameter count (tagged)
3105 // esp[12] = parameter count (tagged)
3106 // esp[16] = address of receiver argument
3107 // Copy arguments header and remaining slots (if there are any).
3108 __ mov(FieldOperand(edi, FixedArray::kMapOffset),
3109 Immediate(FACTORY->fixed_array_map()));
3110 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
3111
3112 Label arguments_loop, arguments_test;
3113 __ mov(ebx, Operand(esp, 1 * kPointerSize));
3114 __ mov(edx, Operand(esp, 4 * kPointerSize));
3115 __ sub(Operand(edx), ebx); // Is there a smarter way to do negative scaling?
3116 __ sub(Operand(edx), ebx);
3117 __ jmp(&arguments_test, Label::kNear);
3118
3119 __ bind(&arguments_loop);
3120 __ sub(Operand(edx), Immediate(kPointerSize));
3121 __ mov(eax, Operand(edx, 0));
3122 __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax);
3123 __ add(Operand(ebx), Immediate(Smi::FromInt(1)));
3124
3125 __ bind(&arguments_test);
3126 __ cmp(ebx, Operand(ecx));
3127 __ j(less, &arguments_loop, Label::kNear);
3128
3129 // Restore.
3130 __ pop(eax); // Address of arguments object.
3131 __ pop(ebx); // Parameter count.
3132
3133 // Return and remove the on-stack parameters.
3134 __ ret(3 * kPointerSize);
3135
3136 // Do the runtime call to allocate the arguments object.
3137 __ bind(&runtime);
3138 __ pop(eax); // Remove saved parameter count.
3139 __ mov(Operand(esp, 1 * kPointerSize), ecx); // Patch argument count.
3140 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
3141 }
3142
3143
3144 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
3145 // esp[0] : return address
3146 // esp[4] : number of parameters
3147 // esp[8] : receiver displacement
3148 // esp[12] : function
2961 3149
2962 // Check if the calling frame is an arguments adaptor frame. 3150 // Check if the calling frame is an arguments adaptor frame.
2963 Label adaptor_frame, try_allocate, runtime; 3151 Label adaptor_frame, try_allocate, runtime;
2964 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 3152 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2965 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); 3153 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
2966 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3154 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2967 __ j(equal, &adaptor_frame); 3155 __ j(equal, &adaptor_frame);
2968 3156
2969 // Get the length from the frame. 3157 // Get the length from the frame.
2970 __ mov(ecx, Operand(esp, 1 * kPointerSize)); 3158 __ mov(ecx, Operand(esp, 1 * kPointerSize));
2971 __ jmp(&try_allocate); 3159 __ jmp(&try_allocate);
2972 3160
2973 // Patch the arguments.length and the parameters pointer. 3161 // Patch the arguments.length and the parameters pointer.
2974 __ bind(&adaptor_frame); 3162 __ bind(&adaptor_frame);
2975 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 3163 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2976 __ mov(Operand(esp, 1 * kPointerSize), ecx); 3164 __ mov(Operand(esp, 1 * kPointerSize), ecx);
2977 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); 3165 __ lea(edx, Operand(edx, ecx, times_2,
3166 StandardFrameConstants::kCallerSPOffset));
2978 __ mov(Operand(esp, 2 * kPointerSize), edx); 3167 __ mov(Operand(esp, 2 * kPointerSize), edx);
2979 3168
2980 // Try the new space allocation. Start out with computing the size of 3169 // Try the new space allocation. Start out with computing the size of
2981 // the arguments object and the elements array. 3170 // the arguments object and the elements array.
2982 Label add_arguments_object; 3171 Label add_arguments_object;
2983 __ bind(&try_allocate); 3172 __ bind(&try_allocate);
2984 __ test(ecx, Operand(ecx)); 3173 __ test(ecx, Operand(ecx));
2985 __ j(zero, &add_arguments_object, Label::kNear); 3174 __ j(zero, &add_arguments_object, Label::kNear);
2986 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); 3175 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
2987 __ bind(&add_arguments_object); 3176 __ bind(&add_arguments_object);
2988 __ add(Operand(ecx), Immediate(GetArgumentsObjectSize())); 3177 __ add(Operand(ecx), Immediate(Heap::kArgumentsObjectSizeStrict));
2989 3178
2990 // Do the allocation of both objects in one go. 3179 // Do the allocation of both objects in one go.
2991 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); 3180 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
2992 3181
2993 // Get the arguments boilerplate from the current (global) context. 3182 // Get the arguments boilerplate from the current (global) context.
2994 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 3183 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2995 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset)); 3184 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset));
2996 __ mov(edi, Operand(edi, 3185 const int offset =
2997 Context::SlotOffset(GetArgumentsBoilerplateIndex()))); 3186 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX);
3187 __ mov(edi, Operand(edi, offset));
2998 3188
2999 // Copy the JS object part. 3189 // Copy the JS object part.
3000 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { 3190 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
3001 __ mov(ebx, FieldOperand(edi, i)); 3191 __ mov(ebx, FieldOperand(edi, i));
3002 __ mov(FieldOperand(eax, i), ebx); 3192 __ mov(FieldOperand(eax, i), ebx);
3003 } 3193 }
3004 3194
3005 if (type_ == NEW_NON_STRICT) {
3006 // Setup the callee in-object property.
3007 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
3008 __ mov(ebx, Operand(esp, 3 * kPointerSize));
3009 __ mov(FieldOperand(eax, JSObject::kHeaderSize +
3010 Heap::kArgumentsCalleeIndex * kPointerSize),
3011 ebx);
3012 }
3013
3014 // Get the length (smi tagged) and set that as an in-object property too. 3195 // Get the length (smi tagged) and set that as an in-object property too.
3015 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 3196 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
3016 __ mov(ecx, Operand(esp, 1 * kPointerSize)); 3197 __ mov(ecx, Operand(esp, 1 * kPointerSize));
3017 __ mov(FieldOperand(eax, JSObject::kHeaderSize + 3198 __ mov(FieldOperand(eax, JSObject::kHeaderSize +
3018 Heap::kArgumentsLengthIndex * kPointerSize), 3199 Heap::kArgumentsLengthIndex * kPointerSize),
3019 ecx); 3200 ecx);
3020 3201
3021 // If there are no actual arguments, we're done. 3202 // If there are no actual arguments, we're done.
3022 Label done; 3203 Label done;
3023 __ test(ecx, Operand(ecx)); 3204 __ test(ecx, Operand(ecx));
3024 __ j(zero, &done); 3205 __ j(zero, &done);
3025 3206
3026 // Get the parameters pointer from the stack. 3207 // Get the parameters pointer from the stack.
3027 __ mov(edx, Operand(esp, 2 * kPointerSize)); 3208 __ mov(edx, Operand(esp, 2 * kPointerSize));
3028 3209
3029 // Setup the elements pointer in the allocated arguments object and 3210 // Setup the elements pointer in the allocated arguments object and
3030 // initialize the header in the elements fixed array. 3211 // initialize the header in the elements fixed array.
3031 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); 3212 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict));
3032 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); 3213 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
3033 __ mov(FieldOperand(edi, FixedArray::kMapOffset), 3214 __ mov(FieldOperand(edi, FixedArray::kMapOffset),
3034 Immediate(masm->isolate()->factory()->fixed_array_map())); 3215 Immediate(FACTORY->fixed_array_map()));
3035 3216
3036 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); 3217 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
3037 // Untag the length for the loop below. 3218 // Untag the length for the loop below.
3038 __ SmiUntag(ecx); 3219 __ SmiUntag(ecx);
3039 3220
3040 // Copy the fixed array slots. 3221 // Copy the fixed array slots.
3041 Label loop; 3222 Label loop;
3042 __ bind(&loop); 3223 __ bind(&loop);
3043 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. 3224 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver.
3044 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); 3225 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx);
3045 __ add(Operand(edi), Immediate(kPointerSize)); 3226 __ add(Operand(edi), Immediate(kPointerSize));
3046 __ sub(Operand(edx), Immediate(kPointerSize)); 3227 __ sub(Operand(edx), Immediate(kPointerSize));
3047 __ dec(ecx); 3228 __ dec(ecx);
3048 __ j(not_zero, &loop); 3229 __ j(not_zero, &loop);
3049 3230
3050 // Return and remove the on-stack parameters. 3231 // Return and remove the on-stack parameters.
3051 __ bind(&done); 3232 __ bind(&done);
3052 __ ret(3 * kPointerSize); 3233 __ ret(3 * kPointerSize);
3053 3234
3054 // Do the runtime call to allocate the arguments object. 3235 // Do the runtime call to allocate the arguments object.
3055 __ bind(&runtime); 3236 __ bind(&runtime);
3056 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 3237 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
3057 } 3238 }
3058 3239
3059 3240
3060 void RegExpExecStub::Generate(MacroAssembler* masm) { 3241 void RegExpExecStub::Generate(MacroAssembler* masm) {
3061 // Just jump directly to runtime if native RegExp is not selected at compile 3242 // Just jump directly to runtime if native RegExp is not selected at compile
3062 // time or if regexp entry in generated code is turned off runtime switch or 3243 // time or if regexp entry in generated code is turned off runtime switch or
3063 // at compilation. 3244 // at compilation.
3064 #ifdef V8_INTERPRETED_REGEXP 3245 #ifdef V8_INTERPRETED_REGEXP
3065 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 3246 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
3066 #else // V8_INTERPRETED_REGEXP 3247 #else // V8_INTERPRETED_REGEXP
(...skipping 22 matching lines...) Expand all
3089 masm->isolate()); 3270 masm->isolate());
3090 ExternalReference address_of_regexp_stack_memory_size = 3271 ExternalReference address_of_regexp_stack_memory_size =
3091 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate()); 3272 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate());
3092 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); 3273 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
3093 __ test(ebx, Operand(ebx)); 3274 __ test(ebx, Operand(ebx));
3094 __ j(zero, &runtime); 3275 __ j(zero, &runtime);
3095 3276
3096 // Check that the first argument is a JSRegExp object. 3277 // Check that the first argument is a JSRegExp object.
3097 __ mov(eax, Operand(esp, kJSRegExpOffset)); 3278 __ mov(eax, Operand(esp, kJSRegExpOffset));
3098 STATIC_ASSERT(kSmiTag == 0); 3279 STATIC_ASSERT(kSmiTag == 0);
3099 __ test(eax, Immediate(kSmiTagMask)); 3280 __ JumpIfSmi(eax, &runtime);
3100 __ j(zero, &runtime);
3101 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); 3281 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx);
3102 __ j(not_equal, &runtime); 3282 __ j(not_equal, &runtime);
3103 // Check that the RegExp has been compiled (data contains a fixed array). 3283 // Check that the RegExp has been compiled (data contains a fixed array).
3104 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); 3284 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
3105 if (FLAG_debug_code) { 3285 if (FLAG_debug_code) {
3106 __ test(ecx, Immediate(kSmiTagMask)); 3286 __ test(ecx, Immediate(kSmiTagMask));
3107 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); 3287 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected");
3108 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); 3288 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx);
3109 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); 3289 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
3110 } 3290 }
(...skipping 13 matching lines...) Expand all
3124 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 3304 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
3125 __ add(Operand(edx), Immediate(2)); // edx was a smi. 3305 __ add(Operand(edx), Immediate(2)); // edx was a smi.
3126 // Check that the static offsets vector buffer is large enough. 3306 // Check that the static offsets vector buffer is large enough.
3127 __ cmp(edx, OffsetsVector::kStaticOffsetsVectorSize); 3307 __ cmp(edx, OffsetsVector::kStaticOffsetsVectorSize);
3128 __ j(above, &runtime); 3308 __ j(above, &runtime);
3129 3309
3130 // ecx: RegExp data (FixedArray) 3310 // ecx: RegExp data (FixedArray)
3131 // edx: Number of capture registers 3311 // edx: Number of capture registers
3132 // Check that the second argument is a string. 3312 // Check that the second argument is a string.
3133 __ mov(eax, Operand(esp, kSubjectOffset)); 3313 __ mov(eax, Operand(esp, kSubjectOffset));
3134 __ test(eax, Immediate(kSmiTagMask)); 3314 __ JumpIfSmi(eax, &runtime);
3135 __ j(zero, &runtime);
3136 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); 3315 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
3137 __ j(NegateCondition(is_string), &runtime); 3316 __ j(NegateCondition(is_string), &runtime);
3138 // Get the length of the string to ebx. 3317 // Get the length of the string to ebx.
3139 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); 3318 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
3140 3319
3141 // ebx: Length of subject string as a smi 3320 // ebx: Length of subject string as a smi
3142 // ecx: RegExp data (FixedArray) 3321 // ecx: RegExp data (FixedArray)
3143 // edx: Number of capture registers 3322 // edx: Number of capture registers
3144 // Check that the third argument is a positive smi less than the subject 3323 // Check that the third argument is a positive smi less than the subject
3145 // string length. A negative value will be greater (unsigned comparison). 3324 // string length. A negative value will be greater (unsigned comparison).
3146 __ mov(eax, Operand(esp, kPreviousIndexOffset)); 3325 __ mov(eax, Operand(esp, kPreviousIndexOffset));
3147 __ test(eax, Immediate(kSmiTagMask)); 3326 __ JumpIfNotSmi(eax, &runtime);
3148 __ j(not_zero, &runtime);
3149 __ cmp(eax, Operand(ebx)); 3327 __ cmp(eax, Operand(ebx));
3150 __ j(above_equal, &runtime); 3328 __ j(above_equal, &runtime);
3151 3329
3152 // ecx: RegExp data (FixedArray) 3330 // ecx: RegExp data (FixedArray)
3153 // edx: Number of capture registers 3331 // edx: Number of capture registers
3154 // Check that the fourth object is a JSArray object. 3332 // Check that the fourth object is a JSArray object.
3155 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); 3333 __ mov(eax, Operand(esp, kLastMatchInfoOffset));
3156 __ test(eax, Immediate(kSmiTagMask)); 3334 __ JumpIfSmi(eax, &runtime);
3157 __ j(zero, &runtime);
3158 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 3335 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
3159 __ j(not_equal, &runtime); 3336 __ j(not_equal, &runtime);
3160 // Check that the JSArray is in fast case. 3337 // Check that the JSArray is in fast case.
3161 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); 3338 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset));
3162 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); 3339 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset));
3163 Factory* factory = masm->isolate()->factory(); 3340 Factory* factory = masm->isolate()->factory();
3164 __ cmp(eax, factory->fixed_array_map()); 3341 __ cmp(eax, factory->fixed_array_map());
3165 __ j(not_equal, &runtime); 3342 __ j(not_equal, &runtime);
3166 // Check that the last match info has space for the capture registers and the 3343 // Check that the last match info has space for the capture registers and the
3167 // additional information. 3344 // additional information.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3225 3402
3226 __ bind(&seq_two_byte_string); 3403 __ bind(&seq_two_byte_string);
3227 // eax: subject string (flat two byte) 3404 // eax: subject string (flat two byte)
3228 // ecx: RegExp data (FixedArray) 3405 // ecx: RegExp data (FixedArray)
3229 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); 3406 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset));
3230 __ Set(edi, Immediate(0)); // Type is two byte. 3407 __ Set(edi, Immediate(0)); // Type is two byte.
3231 3408
3232 __ bind(&check_code); 3409 __ bind(&check_code);
3233 // Check that the irregexp code has been generated for the actual string 3410 // Check that the irregexp code has been generated for the actual string
3234 // encoding. If it has, the field contains a code object otherwise it contains 3411 // encoding. If it has, the field contains a code object otherwise it contains
3235 // the hole. 3412 // a smi (code flushing support).
3236 __ CmpObjectType(edx, CODE_TYPE, ebx); 3413 __ JumpIfSmi(edx, &runtime);
3237 __ j(not_equal, &runtime);
3238 3414
3239 // eax: subject string 3415 // eax: subject string
3240 // edx: code 3416 // edx: code
3241 // edi: encoding of subject string (1 if ascii, 0 if two_byte); 3417 // edi: encoding of subject string (1 if ascii, 0 if two_byte);
3242 // Load used arguments before starting to push arguments for call to native 3418 // Load used arguments before starting to push arguments for call to native
3243 // RegExp code to avoid handling changing stack height. 3419 // RegExp code to avoid handling changing stack height.
3244 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); 3420 __ mov(ebx, Operand(esp, kPreviousIndexOffset));
3245 __ SmiUntag(ebx); // Previous index from smi. 3421 __ SmiUntag(ebx); // Previous index from smi.
3246 3422
3247 // eax: subject string 3423 // eax: subject string
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
3425 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 3601 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
3426 #endif // V8_INTERPRETED_REGEXP 3602 #endif // V8_INTERPRETED_REGEXP
3427 } 3603 }
3428 3604
3429 3605
3430 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { 3606 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
3431 const int kMaxInlineLength = 100; 3607 const int kMaxInlineLength = 100;
3432 Label slowcase; 3608 Label slowcase;
3433 Label done; 3609 Label done;
3434 __ mov(ebx, Operand(esp, kPointerSize * 3)); 3610 __ mov(ebx, Operand(esp, kPointerSize * 3));
3435 __ test(ebx, Immediate(kSmiTagMask)); 3611 __ JumpIfNotSmi(ebx, &slowcase);
3436 __ j(not_zero, &slowcase);
3437 __ cmp(Operand(ebx), Immediate(Smi::FromInt(kMaxInlineLength))); 3612 __ cmp(Operand(ebx), Immediate(Smi::FromInt(kMaxInlineLength)));
3438 __ j(above, &slowcase); 3613 __ j(above, &slowcase);
3439 // Smi-tagging is equivalent to multiplying by 2. 3614 // Smi-tagging is equivalent to multiplying by 2.
3440 STATIC_ASSERT(kSmiTag == 0); 3615 STATIC_ASSERT(kSmiTag == 0);
3441 STATIC_ASSERT(kSmiTagSize == 1); 3616 STATIC_ASSERT(kSmiTagSize == 1);
3442 // Allocate RegExpResult followed by FixedArray with size in ebx. 3617 // Allocate RegExpResult followed by FixedArray with size in ebx.
3443 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] 3618 // JSArray: [Map][empty properties][Elements][Length-smi][index][input]
3444 // Elements: [Map][Length][..elements..] 3619 // Elements: [Map][Length][..elements..]
3445 __ AllocateInNewSpace(JSRegExpResult::kSize + FixedArray::kHeaderSize, 3620 __ AllocateInNewSpace(JSRegExpResult::kSize + FixedArray::kHeaderSize,
3446 times_half_pointer_size, 3621 times_half_pointer_size,
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3538 // doubles is the xor of the upper and lower words. See 3713 // doubles is the xor of the upper and lower words. See
3539 // Heap::GetNumberStringCache. 3714 // Heap::GetNumberStringCache.
3540 Label smi_hash_calculated; 3715 Label smi_hash_calculated;
3541 Label load_result_from_cache; 3716 Label load_result_from_cache;
3542 if (object_is_smi) { 3717 if (object_is_smi) {
3543 __ mov(scratch, object); 3718 __ mov(scratch, object);
3544 __ SmiUntag(scratch); 3719 __ SmiUntag(scratch);
3545 } else { 3720 } else {
3546 Label not_smi; 3721 Label not_smi;
3547 STATIC_ASSERT(kSmiTag == 0); 3722 STATIC_ASSERT(kSmiTag == 0);
3548 __ test(object, Immediate(kSmiTagMask)); 3723 __ JumpIfNotSmi(object, &not_smi, Label::kNear);
3549 __ j(not_zero, &not_smi, Label::kNear);
3550 __ mov(scratch, object); 3724 __ mov(scratch, object);
3551 __ SmiUntag(scratch); 3725 __ SmiUntag(scratch);
3552 __ jmp(&smi_hash_calculated, Label::kNear); 3726 __ jmp(&smi_hash_calculated, Label::kNear);
3553 __ bind(&not_smi); 3727 __ bind(&not_smi);
3554 __ cmp(FieldOperand(object, HeapObject::kMapOffset), 3728 __ cmp(FieldOperand(object, HeapObject::kMapOffset),
3555 masm->isolate()->factory()->heap_number_map()); 3729 masm->isolate()->factory()->heap_number_map());
3556 __ j(not_equal, not_found); 3730 __ j(not_equal, not_found);
3557 STATIC_ASSERT(8 == kDoubleSize); 3731 STATIC_ASSERT(8 == kDoubleSize);
3558 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); 3732 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
3559 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); 3733 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
3560 // Object is heap number and hash is now in scratch. Calculate cache index. 3734 // Object is heap number and hash is now in scratch. Calculate cache index.
3561 __ and_(scratch, Operand(mask)); 3735 __ and_(scratch, Operand(mask));
3562 Register index = scratch; 3736 Register index = scratch;
3563 Register probe = mask; 3737 Register probe = mask;
3564 __ mov(probe, 3738 __ mov(probe,
3565 FieldOperand(number_string_cache, 3739 FieldOperand(number_string_cache,
3566 index, 3740 index,
3567 times_twice_pointer_size, 3741 times_twice_pointer_size,
3568 FixedArray::kHeaderSize)); 3742 FixedArray::kHeaderSize));
3569 __ test(probe, Immediate(kSmiTagMask)); 3743 __ JumpIfSmi(probe, not_found);
3570 __ j(zero, not_found);
3571 if (CpuFeatures::IsSupported(SSE2)) { 3744 if (CpuFeatures::IsSupported(SSE2)) {
3572 CpuFeatures::Scope fscope(SSE2); 3745 CpuFeatures::Scope fscope(SSE2);
3573 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); 3746 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
3574 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); 3747 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
3575 __ ucomisd(xmm0, xmm1); 3748 __ ucomisd(xmm0, xmm1);
3576 } else { 3749 } else {
3577 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); 3750 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset));
3578 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); 3751 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset));
3579 __ FCmp(); 3752 __ FCmp();
3580 } 3753 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3632 void CompareStub::Generate(MacroAssembler* masm) { 3805 void CompareStub::Generate(MacroAssembler* masm) {
3633 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); 3806 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
3634 3807
3635 Label check_unequal_objects, done; 3808 Label check_unequal_objects, done;
3636 3809
3637 // Compare two smis if required. 3810 // Compare two smis if required.
3638 if (include_smi_compare_) { 3811 if (include_smi_compare_) {
3639 Label non_smi, smi_done; 3812 Label non_smi, smi_done;
3640 __ mov(ecx, Operand(edx)); 3813 __ mov(ecx, Operand(edx));
3641 __ or_(ecx, Operand(eax)); 3814 __ or_(ecx, Operand(eax));
3642 __ test(ecx, Immediate(kSmiTagMask)); 3815 __ JumpIfNotSmi(ecx, &non_smi);
3643 __ j(not_zero, &non_smi);
3644 __ sub(edx, Operand(eax)); // Return on the result of the subtraction. 3816 __ sub(edx, Operand(eax)); // Return on the result of the subtraction.
3645 __ j(no_overflow, &smi_done); 3817 __ j(no_overflow, &smi_done);
3646 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. 3818 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here.
3647 __ bind(&smi_done); 3819 __ bind(&smi_done);
3648 __ mov(eax, edx); 3820 __ mov(eax, edx);
3649 __ ret(0); 3821 __ ret(0);
3650 __ bind(&non_smi); 3822 __ bind(&non_smi);
3651 } else if (FLAG_debug_code) { 3823 } else if (FLAG_debug_code) {
3652 __ mov(ecx, Operand(edx)); 3824 __ mov(ecx, Operand(edx));
3653 __ or_(ecx, Operand(eax)); 3825 __ or_(ecx, Operand(eax));
(...skipping 28 matching lines...) Expand all
3682 if (never_nan_nan_ && (cc_ == equal)) { 3854 if (never_nan_nan_ && (cc_ == equal)) {
3683 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 3855 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
3684 __ ret(0); 3856 __ ret(0);
3685 } else { 3857 } else {
3686 Label heap_number; 3858 Label heap_number;
3687 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 3859 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3688 Immediate(masm->isolate()->factory()->heap_number_map())); 3860 Immediate(masm->isolate()->factory()->heap_number_map()));
3689 __ j(equal, &heap_number, Label::kNear); 3861 __ j(equal, &heap_number, Label::kNear);
3690 if (cc_ != equal) { 3862 if (cc_ != equal) {
3691 // Call runtime on identical JSObjects. Otherwise return equal. 3863 // Call runtime on identical JSObjects. Otherwise return equal.
3692 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 3864 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
3693 __ j(above_equal, &not_identical); 3865 __ j(above_equal, &not_identical);
3694 } 3866 }
3695 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 3867 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
3696 __ ret(0); 3868 __ ret(0);
3697 3869
3698 __ bind(&heap_number); 3870 __ bind(&heap_number);
3699 // It is a heap number, so return non-equal if it's NaN and equal if 3871 // It is a heap number, so return non-equal if it's NaN and equal if
3700 // it's not NaN. 3872 // it's not NaN.
3701 // The representation of NaN values has all exponent bits (52..62) set, 3873 // The representation of NaN values has all exponent bits (52..62) set,
3702 // and not all mantissa bits (0..51) clear. 3874 // and not all mantissa bits (0..51) clear.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3770 __ ret(0); 3942 __ ret(0);
3771 3943
3772 __ bind(&not_smis); 3944 __ bind(&not_smis);
3773 // If either operand is a JSObject or an oddball value, then they are not 3945 // If either operand is a JSObject or an oddball value, then they are not
3774 // equal since their pointers are different 3946 // equal since their pointers are different
3775 // There is no test for undetectability in strict equality. 3947 // There is no test for undetectability in strict equality.
3776 3948
3777 // Get the type of the first operand. 3949 // Get the type of the first operand.
3778 // If the first object is a JS object, we have done pointer comparison. 3950 // If the first object is a JS object, we have done pointer comparison.
3779 Label first_non_object; 3951 Label first_non_object;
3780 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 3952 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
3781 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 3953 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
3782 __ j(below, &first_non_object, Label::kNear); 3954 __ j(below, &first_non_object, Label::kNear);
3783 3955
3784 // Return non-zero (eax is not zero) 3956 // Return non-zero (eax is not zero)
3785 Label return_not_equal; 3957 Label return_not_equal;
3786 STATIC_ASSERT(kHeapObjectTag != 0); 3958 STATIC_ASSERT(kHeapObjectTag != 0);
3787 __ bind(&return_not_equal); 3959 __ bind(&return_not_equal);
3788 __ ret(0); 3960 __ ret(0);
3789 3961
3790 __ bind(&first_non_object); 3962 __ bind(&first_non_object);
3791 // Check for oddballs: true, false, null, undefined. 3963 // Check for oddballs: true, false, null, undefined.
3792 __ CmpInstanceType(ecx, ODDBALL_TYPE); 3964 __ CmpInstanceType(ecx, ODDBALL_TYPE);
3793 __ j(equal, &return_not_equal); 3965 __ j(equal, &return_not_equal);
3794 3966
3795 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx); 3967 __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ecx);
3796 __ j(above_equal, &return_not_equal); 3968 __ j(above_equal, &return_not_equal);
3797 3969
3798 // Check for oddballs: true, false, null, undefined. 3970 // Check for oddballs: true, false, null, undefined.
3799 __ CmpInstanceType(ecx, ODDBALL_TYPE); 3971 __ CmpInstanceType(ecx, ODDBALL_TYPE);
3800 __ j(equal, &return_not_equal); 3972 __ j(equal, &return_not_equal);
3801 3973
3802 // Fall through to the general case. 3974 // Fall through to the general case.
3803 __ bind(&slow); 3975 __ bind(&slow);
3804 } 3976 }
3805 3977
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
3909 Label not_both_objects; 4081 Label not_both_objects;
3910 Label return_unequal; 4082 Label return_unequal;
3911 // At most one is a smi, so we can test for smi by adding the two. 4083 // At most one is a smi, so we can test for smi by adding the two.
3912 // A smi plus a heap object has the low bit set, a heap object plus 4084 // A smi plus a heap object has the low bit set, a heap object plus
3913 // a heap object has the low bit clear. 4085 // a heap object has the low bit clear.
3914 STATIC_ASSERT(kSmiTag == 0); 4086 STATIC_ASSERT(kSmiTag == 0);
3915 STATIC_ASSERT(kSmiTagMask == 1); 4087 STATIC_ASSERT(kSmiTagMask == 1);
3916 __ lea(ecx, Operand(eax, edx, times_1, 0)); 4088 __ lea(ecx, Operand(eax, edx, times_1, 0));
3917 __ test(ecx, Immediate(kSmiTagMask)); 4089 __ test(ecx, Immediate(kSmiTagMask));
3918 __ j(not_zero, &not_both_objects, Label::kNear); 4090 __ j(not_zero, &not_both_objects, Label::kNear);
3919 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 4091 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
3920 __ j(below, &not_both_objects, Label::kNear); 4092 __ j(below, &not_both_objects, Label::kNear);
3921 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx); 4093 __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ebx);
3922 __ j(below, &not_both_objects, Label::kNear); 4094 __ j(below, &not_both_objects, Label::kNear);
3923 // We do not bail out after this point. Both are JSObjects, and 4095 // We do not bail out after this point. Both are JSObjects, and
3924 // they are equal if and only if both are undetectable. 4096 // they are equal if and only if both are undetectable.
3925 // The and of the undetectable flags is 1 if and only if they are equal. 4097 // The and of the undetectable flags is 1 if and only if they are equal.
3926 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 4098 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
3927 1 << Map::kIsUndetectable); 4099 1 << Map::kIsUndetectable);
3928 __ j(zero, &return_unequal, Label::kNear); 4100 __ j(zero, &return_unequal, Label::kNear);
3929 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), 4101 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
3930 1 << Map::kIsUndetectable); 4102 1 << Map::kIsUndetectable);
3931 __ j(zero, &return_unequal, Label::kNear); 4103 __ j(zero, &return_unequal, Label::kNear);
(...skipping 27 matching lines...) Expand all
3959 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 4131 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
3960 // tagged as a small integer. 4132 // tagged as a small integer.
3961 __ InvokeBuiltin(builtin, JUMP_FUNCTION); 4133 __ InvokeBuiltin(builtin, JUMP_FUNCTION);
3962 } 4134 }
3963 4135
3964 4136
3965 void CompareStub::BranchIfNonSymbol(MacroAssembler* masm, 4137 void CompareStub::BranchIfNonSymbol(MacroAssembler* masm,
3966 Label* label, 4138 Label* label,
3967 Register object, 4139 Register object,
3968 Register scratch) { 4140 Register scratch) {
3969 __ test(object, Immediate(kSmiTagMask)); 4141 __ JumpIfSmi(object, label);
3970 __ j(zero, label);
3971 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); 4142 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset));
3972 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 4143 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3973 __ and_(scratch, kIsSymbolMask | kIsNotStringMask); 4144 __ and_(scratch, kIsSymbolMask | kIsNotStringMask);
3974 __ cmp(scratch, kSymbolTag | kStringTag); 4145 __ cmp(scratch, kSymbolTag | kStringTag);
3975 __ j(not_equal, label); 4146 __ j(not_equal, label);
3976 } 4147 }
3977 4148
3978 4149
3979 void StackCheckStub::Generate(MacroAssembler* masm) { 4150 void StackCheckStub::Generate(MacroAssembler* masm) {
3980 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); 4151 __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
(...skipping 19 matching lines...) Expand all
4000 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 4171 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
4001 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), ebx); 4172 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), ebx);
4002 __ bind(&call); 4173 __ bind(&call);
4003 } 4174 }
4004 4175
4005 // Get the function to call from the stack. 4176 // Get the function to call from the stack.
4006 // +2 ~ receiver, return address 4177 // +2 ~ receiver, return address
4007 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); 4178 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize));
4008 4179
4009 // Check that the function really is a JavaScript function. 4180 // Check that the function really is a JavaScript function.
4010 __ test(edi, Immediate(kSmiTagMask)); 4181 __ JumpIfSmi(edi, &slow);
4011 __ j(zero, &slow);
4012 // Goto slow case if we do not have a function. 4182 // Goto slow case if we do not have a function.
4013 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 4183 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
4014 __ j(not_equal, &slow); 4184 __ j(not_equal, &slow);
4015 4185
4016 // Fast-case: Just invoke the function. 4186 // Fast-case: Just invoke the function.
4017 ParameterCount actual(argc_); 4187 ParameterCount actual(argc_);
4018 4188
4019 if (ReceiverMightBeImplicit()) { 4189 if (ReceiverMightBeImplicit()) {
4020 Label call_as_function; 4190 Label call_as_function;
4021 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); 4191 __ cmp(eax, masm->isolate()->factory()->the_hole_value());
4022 __ j(equal, &call_as_function); 4192 __ j(equal, &call_as_function);
4023 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 4193 __ InvokeFunction(edi,
4194 actual,
4195 JUMP_FUNCTION,
4196 NullCallWrapper(),
4197 CALL_AS_METHOD);
4024 __ bind(&call_as_function); 4198 __ bind(&call_as_function);
4025 } 4199 }
4026 __ InvokeFunction(edi, 4200 __ InvokeFunction(edi,
4027 actual, 4201 actual,
4028 JUMP_FUNCTION, 4202 JUMP_FUNCTION,
4029 NullCallWrapper(), 4203 NullCallWrapper(),
4030 CALL_AS_FUNCTION); 4204 CALL_AS_FUNCTION);
4031 4205
4032 // Slow-case: Non-function called. 4206 // Slow-case: Non-function called.
4033 __ bind(&slow); 4207 __ bind(&slow);
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
4396 ASSERT_EQ(function.code(), InstanceofStub::right().code()); 4570 ASSERT_EQ(function.code(), InstanceofStub::right().code());
4397 4571
4398 // Get the object and function - they are always both needed. 4572 // Get the object and function - they are always both needed.
4399 Label slow, not_js_object; 4573 Label slow, not_js_object;
4400 if (!HasArgsInRegisters()) { 4574 if (!HasArgsInRegisters()) {
4401 __ mov(object, Operand(esp, 2 * kPointerSize)); 4575 __ mov(object, Operand(esp, 2 * kPointerSize));
4402 __ mov(function, Operand(esp, 1 * kPointerSize)); 4576 __ mov(function, Operand(esp, 1 * kPointerSize));
4403 } 4577 }
4404 4578
4405 // Check that the left hand is a JS object. 4579 // Check that the left hand is a JS object.
4406 __ test(object, Immediate(kSmiTagMask)); 4580 __ JumpIfSmi(object, &not_js_object);
4407 __ j(zero, &not_js_object);
4408 __ IsObjectJSObjectType(object, map, scratch, &not_js_object); 4581 __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
4409 4582
4410 // If there is a call site cache don't look in the global cache, but do the 4583 // If there is a call site cache don't look in the global cache, but do the
4411 // real lookup and update the call site cache. 4584 // real lookup and update the call site cache.
4412 if (!HasCallSiteInlineCheck()) { 4585 if (!HasCallSiteInlineCheck()) {
4413 // Look up the function and the map in the instanceof cache. 4586 // Look up the function and the map in the instanceof cache.
4414 Label miss; 4587 Label miss;
4415 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); 4588 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
4416 __ cmp(function, 4589 __ cmp(function,
4417 Operand::StaticArray(scratch, times_pointer_size, roots_address)); 4590 Operand::StaticArray(scratch, times_pointer_size, roots_address));
4418 __ j(not_equal, &miss, Label::kNear); 4591 __ j(not_equal, &miss, Label::kNear);
4419 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); 4592 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
4420 __ cmp(map, Operand::StaticArray( 4593 __ cmp(map, Operand::StaticArray(
4421 scratch, times_pointer_size, roots_address)); 4594 scratch, times_pointer_size, roots_address));
4422 __ j(not_equal, &miss, Label::kNear); 4595 __ j(not_equal, &miss, Label::kNear);
4423 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); 4596 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
4424 __ mov(eax, Operand::StaticArray( 4597 __ mov(eax, Operand::StaticArray(
4425 scratch, times_pointer_size, roots_address)); 4598 scratch, times_pointer_size, roots_address));
4426 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4599 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4427 __ bind(&miss); 4600 __ bind(&miss);
4428 } 4601 }
4429 4602
4430 // Get the prototype of the function. 4603 // Get the prototype of the function.
4431 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); 4604 __ TryGetFunctionPrototype(function, prototype, scratch, &slow);
4432 4605
4433 // Check that the function prototype is a JS object. 4606 // Check that the function prototype is a JS object.
4434 __ test(prototype, Immediate(kSmiTagMask)); 4607 __ JumpIfSmi(prototype, &slow);
4435 __ j(zero, &slow);
4436 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); 4608 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
4437 4609
4438 // Update the global instanceof or call site inlined cache with the current 4610 // Update the global instanceof or call site inlined cache with the current
4439 // map and function. The cached answer will be set when it is known below. 4611 // map and function. The cached answer will be set when it is known below.
4440 if (!HasCallSiteInlineCheck()) { 4612 if (!HasCallSiteInlineCheck()) {
4441 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); 4613 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
4442 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map); 4614 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map);
4443 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); 4615 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
4444 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), 4616 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address),
4445 function); 4617 function);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
4514 if (!ReturnTrueFalseObject()) { 4686 if (!ReturnTrueFalseObject()) {
4515 __ Set(eax, Immediate(Smi::FromInt(1))); 4687 __ Set(eax, Immediate(Smi::FromInt(1)));
4516 } 4688 }
4517 } 4689 }
4518 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4690 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4519 4691
4520 Label object_not_null, object_not_null_or_smi; 4692 Label object_not_null, object_not_null_or_smi;
4521 __ bind(&not_js_object); 4693 __ bind(&not_js_object);
4522 // Before null, smi and string value checks, check that the rhs is a function 4694 // Before null, smi and string value checks, check that the rhs is a function
4523 // as for a non-function rhs an exception needs to be thrown. 4695 // as for a non-function rhs an exception needs to be thrown.
4524 __ test(function, Immediate(kSmiTagMask)); 4696 __ JumpIfSmi(function, &slow);
4525 __ j(zero, &slow);
4526 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); 4697 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
4527 __ j(not_equal, &slow); 4698 __ j(not_equal, &slow);
4528 4699
4529 // Null is not instance of anything. 4700 // Null is not instance of anything.
4530 __ cmp(object, factory->null_value()); 4701 __ cmp(object, factory->null_value());
4531 __ j(not_equal, &object_not_null); 4702 __ j(not_equal, &object_not_null);
4532 __ Set(eax, Immediate(Smi::FromInt(1))); 4703 __ Set(eax, Immediate(Smi::FromInt(1)));
4533 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4704 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4534 4705
4535 __ bind(&object_not_null); 4706 __ bind(&object_not_null);
4536 // Smi values is not instance of anything. 4707 // Smi values is not instance of anything.
4537 __ test(object, Immediate(kSmiTagMask)); 4708 __ JumpIfNotSmi(object, &object_not_null_or_smi);
4538 __ j(not_zero, &object_not_null_or_smi);
4539 __ Set(eax, Immediate(Smi::FromInt(1))); 4709 __ Set(eax, Immediate(Smi::FromInt(1)));
4540 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4710 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4541 4711
4542 __ bind(&object_not_null_or_smi); 4712 __ bind(&object_not_null_or_smi);
4543 // String values is not instance of anything. 4713 // String values is not instance of anything.
4544 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); 4714 Condition is_string = masm->IsObjectStringType(object, scratch, scratch);
4545 __ j(NegateCondition(is_string), &slow); 4715 __ j(NegateCondition(is_string), &slow);
4546 __ Set(eax, Immediate(Smi::FromInt(1))); 4716 __ Set(eax, Immediate(Smi::FromInt(1)));
4547 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4717 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4548 4718
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
4655 // ------------------------------------------------------------------------- 4825 // -------------------------------------------------------------------------
4656 // StringCharCodeAtGenerator 4826 // StringCharCodeAtGenerator
4657 4827
4658 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 4828 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
4659 Label flat_string; 4829 Label flat_string;
4660 Label ascii_string; 4830 Label ascii_string;
4661 Label got_char_code; 4831 Label got_char_code;
4662 4832
4663 // If the receiver is a smi trigger the non-string case. 4833 // If the receiver is a smi trigger the non-string case.
4664 STATIC_ASSERT(kSmiTag == 0); 4834 STATIC_ASSERT(kSmiTag == 0);
4665 __ test(object_, Immediate(kSmiTagMask)); 4835 __ JumpIfSmi(object_, receiver_not_string_);
4666 __ j(zero, receiver_not_string_);
4667 4836
4668 // Fetch the instance type of the receiver into result register. 4837 // Fetch the instance type of the receiver into result register.
4669 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 4838 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
4670 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 4839 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
4671 // If the receiver is not a string trigger the non-string case. 4840 // If the receiver is not a string trigger the non-string case.
4672 __ test(result_, Immediate(kIsNotStringMask)); 4841 __ test(result_, Immediate(kIsNotStringMask));
4673 __ j(not_zero, receiver_not_string_); 4842 __ j(not_zero, receiver_not_string_);
4674 4843
4675 // If the index is non-smi trigger the non-smi case. 4844 // If the index is non-smi trigger the non-smi case.
4676 STATIC_ASSERT(kSmiTag == 0); 4845 STATIC_ASSERT(kSmiTag == 0);
4677 __ test(index_, Immediate(kSmiTagMask)); 4846 __ JumpIfNotSmi(index_, &index_not_smi_);
4678 __ j(not_zero, &index_not_smi_);
4679 4847
4680 // Put smi-tagged index into scratch register. 4848 // Put smi-tagged index into scratch register.
4681 __ mov(scratch_, index_); 4849 __ mov(scratch_, index_);
4682 __ bind(&got_smi_index_); 4850 __ bind(&got_smi_index_);
4683 4851
4684 // Check for index out of range. 4852 // Check for index out of range.
4685 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset)); 4853 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset));
4686 __ j(above_equal, index_out_of_range_); 4854 __ j(above_equal, index_out_of_range_);
4687 4855
4688 // We need special handling for non-flat strings. 4856 // We need special handling for non-flat strings.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
4766 __ mov(scratch_, eax); 4934 __ mov(scratch_, eax);
4767 } 4935 }
4768 __ pop(index_); 4936 __ pop(index_);
4769 __ pop(object_); 4937 __ pop(object_);
4770 // Reload the instance type. 4938 // Reload the instance type.
4771 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 4939 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
4772 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 4940 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
4773 call_helper.AfterCall(masm); 4941 call_helper.AfterCall(masm);
4774 // If index is still not a smi, it must be out of range. 4942 // If index is still not a smi, it must be out of range.
4775 STATIC_ASSERT(kSmiTag == 0); 4943 STATIC_ASSERT(kSmiTag == 0);
4776 __ test(scratch_, Immediate(kSmiTagMask)); 4944 __ JumpIfNotSmi(scratch_, index_out_of_range_);
4777 __ j(not_zero, index_out_of_range_);
4778 // Otherwise, return to the fast path. 4945 // Otherwise, return to the fast path.
4779 __ jmp(&got_smi_index_); 4946 __ jmp(&got_smi_index_);
4780 4947
4781 // Call runtime. We get here when the receiver is a string and the 4948 // Call runtime. We get here when the receiver is a string and the
4782 // index is a number, but the code of getting the actual character 4949 // index is a number, but the code of getting the actual character
4783 // is too complex (e.g., when the string needs to be flattened). 4950 // is too complex (e.g., when the string needs to be flattened).
4784 __ bind(&call_runtime_); 4951 __ bind(&call_runtime_);
4785 call_helper.BeforeCall(masm); 4952 call_helper.BeforeCall(masm);
4786 __ push(object_); 4953 __ push(object_);
4787 __ push(index_); 4954 __ push(index_);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
4861 void StringAddStub::Generate(MacroAssembler* masm) { 5028 void StringAddStub::Generate(MacroAssembler* masm) {
4862 Label string_add_runtime, call_builtin; 5029 Label string_add_runtime, call_builtin;
4863 Builtins::JavaScript builtin_id = Builtins::ADD; 5030 Builtins::JavaScript builtin_id = Builtins::ADD;
4864 5031
4865 // Load the two arguments. 5032 // Load the two arguments.
4866 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 5033 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
4867 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 5034 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
4868 5035
4869 // Make sure that both arguments are strings if not known in advance. 5036 // Make sure that both arguments are strings if not known in advance.
4870 if (flags_ == NO_STRING_ADD_FLAGS) { 5037 if (flags_ == NO_STRING_ADD_FLAGS) {
4871 __ test(eax, Immediate(kSmiTagMask)); 5038 __ JumpIfSmi(eax, &string_add_runtime);
4872 __ j(zero, &string_add_runtime);
4873 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); 5039 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx);
4874 __ j(above_equal, &string_add_runtime); 5040 __ j(above_equal, &string_add_runtime);
4875 5041
4876 // First argument is a a string, test second. 5042 // First argument is a a string, test second.
4877 __ test(edx, Immediate(kSmiTagMask)); 5043 __ JumpIfSmi(edx, &string_add_runtime);
4878 __ j(zero, &string_add_runtime);
4879 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); 5044 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
4880 __ j(above_equal, &string_add_runtime); 5045 __ j(above_equal, &string_add_runtime);
4881 } else { 5046 } else {
4882 // Here at least one of the arguments is definitely a string. 5047 // Here at least one of the arguments is definitely a string.
4883 // We convert the one that is not known to be a string. 5048 // We convert the one that is not known to be a string.
4884 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { 5049 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
4885 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); 5050 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
4886 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi, 5051 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi,
4887 &call_builtin); 5052 &call_builtin);
4888 builtin_id = Builtins::STRING_ADD_RIGHT; 5053 builtin_id = Builtins::STRING_ADD_RIGHT;
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
5136 5301
5137 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, 5302 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
5138 int stack_offset, 5303 int stack_offset,
5139 Register arg, 5304 Register arg,
5140 Register scratch1, 5305 Register scratch1,
5141 Register scratch2, 5306 Register scratch2,
5142 Register scratch3, 5307 Register scratch3,
5143 Label* slow) { 5308 Label* slow) {
5144 // First check if the argument is already a string. 5309 // First check if the argument is already a string.
5145 Label not_string, done; 5310 Label not_string, done;
5146 __ test(arg, Immediate(kSmiTagMask)); 5311 __ JumpIfSmi(arg, &not_string);
5147 __ j(zero, &not_string);
5148 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1); 5312 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
5149 __ j(below, &done); 5313 __ j(below, &done);
5150 5314
5151 // Check the number to string cache. 5315 // Check the number to string cache.
5152 Label not_cached; 5316 Label not_cached;
5153 __ bind(&not_string); 5317 __ bind(&not_string);
5154 // Puts the cached result into scratch1. 5318 // Puts the cached result into scratch1.
5155 NumberToStringStub::GenerateLookupNumberStringCache(masm, 5319 NumberToStringStub::GenerateLookupNumberStringCache(masm,
5156 arg, 5320 arg,
5157 scratch1, 5321 scratch1,
5158 scratch2, 5322 scratch2,
5159 scratch3, 5323 scratch3,
5160 false, 5324 false,
5161 &not_cached); 5325 &not_cached);
5162 __ mov(arg, scratch1); 5326 __ mov(arg, scratch1);
5163 __ mov(Operand(esp, stack_offset), arg); 5327 __ mov(Operand(esp, stack_offset), arg);
5164 __ jmp(&done); 5328 __ jmp(&done);
5165 5329
5166 // Check if the argument is a safe string wrapper. 5330 // Check if the argument is a safe string wrapper.
5167 __ bind(&not_cached); 5331 __ bind(&not_cached);
5168 __ test(arg, Immediate(kSmiTagMask)); 5332 __ JumpIfSmi(arg, slow);
5169 __ j(zero, slow);
5170 __ CmpObjectType(arg, JS_VALUE_TYPE, scratch1); // map -> scratch1. 5333 __ CmpObjectType(arg, JS_VALUE_TYPE, scratch1); // map -> scratch1.
5171 __ j(not_equal, slow); 5334 __ j(not_equal, slow);
5172 __ test_b(FieldOperand(scratch1, Map::kBitField2Offset), 5335 __ test_b(FieldOperand(scratch1, Map::kBitField2Offset),
5173 1 << Map::kStringWrapperSafeForDefaultValueOf); 5336 1 << Map::kStringWrapperSafeForDefaultValueOf);
5174 __ j(zero, slow); 5337 __ j(zero, slow);
5175 __ mov(arg, FieldOperand(arg, JSValue::kValueOffset)); 5338 __ mov(arg, FieldOperand(arg, JSValue::kValueOffset));
5176 __ mov(Operand(esp, stack_offset), arg); 5339 __ mov(Operand(esp, stack_offset), arg);
5177 5340
5178 __ bind(&done); 5341 __ bind(&done);
5179 } 5342 }
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
5453 5616
5454 // Stack frame on entry. 5617 // Stack frame on entry.
5455 // esp[0]: return address 5618 // esp[0]: return address
5456 // esp[4]: to 5619 // esp[4]: to
5457 // esp[8]: from 5620 // esp[8]: from
5458 // esp[12]: string 5621 // esp[12]: string
5459 5622
5460 // Make sure first argument is a string. 5623 // Make sure first argument is a string.
5461 __ mov(eax, Operand(esp, 3 * kPointerSize)); 5624 __ mov(eax, Operand(esp, 3 * kPointerSize));
5462 STATIC_ASSERT(kSmiTag == 0); 5625 STATIC_ASSERT(kSmiTag == 0);
5463 __ test(eax, Immediate(kSmiTagMask)); 5626 __ JumpIfSmi(eax, &runtime);
5464 __ j(zero, &runtime);
5465 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); 5627 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
5466 __ j(NegateCondition(is_string), &runtime); 5628 __ j(NegateCondition(is_string), &runtime);
5467 5629
5468 // eax: string 5630 // eax: string
5469 // ebx: instance type 5631 // ebx: instance type
5470 5632
5471 // Calculate length of sub string using the smi values. 5633 // Calculate length of sub string using the smi values.
5472 Label result_longer_than_two; 5634 Label result_longer_than_two;
5473 __ mov(ecx, Operand(esp, 1 * kPointerSize)); // To index. 5635 __ mov(ecx, Operand(esp, 1 * kPointerSize)); // To index.
5474 __ test(ecx, Immediate(kSmiTagMask)); 5636 __ JumpIfNotSmi(ecx, &runtime);
5475 __ j(not_zero, &runtime);
5476 __ mov(edx, Operand(esp, 2 * kPointerSize)); // From index. 5637 __ mov(edx, Operand(esp, 2 * kPointerSize)); // From index.
5477 __ test(edx, Immediate(kSmiTagMask)); 5638 __ JumpIfNotSmi(edx, &runtime);
5478 __ j(not_zero, &runtime);
5479 __ sub(ecx, Operand(edx)); 5639 __ sub(ecx, Operand(edx));
5480 __ cmp(ecx, FieldOperand(eax, String::kLengthOffset)); 5640 __ cmp(ecx, FieldOperand(eax, String::kLengthOffset));
5481 Label return_eax; 5641 Label return_eax;
5482 __ j(equal, &return_eax); 5642 __ j(equal, &return_eax);
5483 // Special handling of sub-strings of length 1 and 2. One character strings 5643 // Special handling of sub-strings of length 1 and 2. One character strings
5484 // are handled in the runtime system (looked up in the single character 5644 // are handled in the runtime system (looked up in the single character
5485 // cache). Two character strings are looked for in the symbol cache. 5645 // cache). Two character strings are looked for in the symbol cache.
5486 __ SmiUntag(ecx); // Result length is no longer smi. 5646 __ SmiUntag(ecx); // Result length is no longer smi.
5487 __ cmp(ecx, 2); 5647 __ cmp(ecx, 2);
5488 __ j(greater, &result_longer_than_two); 5648 __ j(greater, &result_longer_than_two);
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
5760 __ bind(&runtime); 5920 __ bind(&runtime);
5761 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 5921 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
5762 } 5922 }
5763 5923
5764 5924
5765 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { 5925 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
5766 ASSERT(state_ == CompareIC::SMIS); 5926 ASSERT(state_ == CompareIC::SMIS);
5767 Label miss; 5927 Label miss;
5768 __ mov(ecx, Operand(edx)); 5928 __ mov(ecx, Operand(edx));
5769 __ or_(ecx, Operand(eax)); 5929 __ or_(ecx, Operand(eax));
5770 __ test(ecx, Immediate(kSmiTagMask)); 5930 __ JumpIfNotSmi(ecx, &miss, Label::kNear);
5771 __ j(not_zero, &miss, Label::kNear);
5772 5931
5773 if (GetCondition() == equal) { 5932 if (GetCondition() == equal) {
5774 // For equality we do not care about the sign of the result. 5933 // For equality we do not care about the sign of the result.
5775 __ sub(eax, Operand(edx)); 5934 __ sub(eax, Operand(edx));
5776 } else { 5935 } else {
5777 Label done; 5936 Label done;
5778 __ sub(edx, Operand(eax)); 5937 __ sub(edx, Operand(eax));
5779 __ j(no_overflow, &done, Label::kNear); 5938 __ j(no_overflow, &done, Label::kNear);
5780 // Correct sign of result in case of overflow. 5939 // Correct sign of result in case of overflow.
5781 __ not_(edx); 5940 __ not_(edx);
5782 __ bind(&done); 5941 __ bind(&done);
5783 __ mov(eax, edx); 5942 __ mov(eax, edx);
5784 } 5943 }
5785 __ ret(0); 5944 __ ret(0);
5786 5945
5787 __ bind(&miss); 5946 __ bind(&miss);
5788 GenerateMiss(masm); 5947 GenerateMiss(masm);
5789 } 5948 }
5790 5949
5791 5950
5792 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { 5951 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
5793 ASSERT(state_ == CompareIC::HEAP_NUMBERS); 5952 ASSERT(state_ == CompareIC::HEAP_NUMBERS);
5794 5953
5795 Label generic_stub; 5954 Label generic_stub;
5796 Label unordered; 5955 Label unordered;
5797 Label miss; 5956 Label miss;
5798 __ mov(ecx, Operand(edx)); 5957 __ mov(ecx, Operand(edx));
5799 __ and_(ecx, Operand(eax)); 5958 __ and_(ecx, Operand(eax));
5800 __ test(ecx, Immediate(kSmiTagMask)); 5959 __ JumpIfSmi(ecx, &generic_stub, Label::kNear);
5801 __ j(zero, &generic_stub, Label::kNear);
5802 5960
5803 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); 5961 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx);
5804 __ j(not_equal, &miss, Label::kNear); 5962 __ j(not_equal, &miss, Label::kNear);
5805 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); 5963 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
5806 __ j(not_equal, &miss, Label::kNear); 5964 __ j(not_equal, &miss, Label::kNear);
5807 5965
5808 // Inlining the double comparison and falling back to the general compare 5966 // Inlining the double comparison and falling back to the general compare
5809 // stub if NaN is involved or SS2 or CMOV is unsupported. 5967 // stub if NaN is involved or SS2 or CMOV is unsupported.
5810 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { 5968 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) {
5811 CpuFeatures::Scope scope1(SSE2); 5969 CpuFeatures::Scope scope1(SSE2);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
5850 Register left = edx; 6008 Register left = edx;
5851 Register right = eax; 6009 Register right = eax;
5852 Register tmp1 = ecx; 6010 Register tmp1 = ecx;
5853 Register tmp2 = ebx; 6011 Register tmp2 = ebx;
5854 6012
5855 // Check that both operands are heap objects. 6013 // Check that both operands are heap objects.
5856 Label miss; 6014 Label miss;
5857 __ mov(tmp1, Operand(left)); 6015 __ mov(tmp1, Operand(left));
5858 STATIC_ASSERT(kSmiTag == 0); 6016 STATIC_ASSERT(kSmiTag == 0);
5859 __ and_(tmp1, Operand(right)); 6017 __ and_(tmp1, Operand(right));
5860 __ test(tmp1, Immediate(kSmiTagMask)); 6018 __ JumpIfSmi(tmp1, &miss, Label::kNear);
5861 __ j(zero, &miss, Label::kNear);
5862 6019
5863 // Check that both operands are symbols. 6020 // Check that both operands are symbols.
5864 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 6021 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
5865 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 6022 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
5866 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 6023 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
5867 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 6024 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
5868 STATIC_ASSERT(kSymbolTag != 0); 6025 STATIC_ASSERT(kSymbolTag != 0);
5869 __ and_(tmp1, Operand(tmp2)); 6026 __ and_(tmp1, Operand(tmp2));
5870 __ test(tmp1, Immediate(kIsSymbolMask)); 6027 __ test(tmp1, Immediate(kIsSymbolMask));
5871 __ j(zero, &miss, Label::kNear); 6028 __ j(zero, &miss, Label::kNear);
(...skipping 25 matching lines...) Expand all
5897 Register left = edx; 6054 Register left = edx;
5898 Register right = eax; 6055 Register right = eax;
5899 Register tmp1 = ecx; 6056 Register tmp1 = ecx;
5900 Register tmp2 = ebx; 6057 Register tmp2 = ebx;
5901 Register tmp3 = edi; 6058 Register tmp3 = edi;
5902 6059
5903 // Check that both operands are heap objects. 6060 // Check that both operands are heap objects.
5904 __ mov(tmp1, Operand(left)); 6061 __ mov(tmp1, Operand(left));
5905 STATIC_ASSERT(kSmiTag == 0); 6062 STATIC_ASSERT(kSmiTag == 0);
5906 __ and_(tmp1, Operand(right)); 6063 __ and_(tmp1, Operand(right));
5907 __ test(tmp1, Immediate(kSmiTagMask)); 6064 __ JumpIfSmi(tmp1, &miss);
5908 __ j(zero, &miss);
5909 6065
5910 // Check that both operands are strings. This leaves the instance 6066 // Check that both operands are strings. This leaves the instance
5911 // types loaded in tmp1 and tmp2. 6067 // types loaded in tmp1 and tmp2.
5912 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); 6068 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
5913 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); 6069 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
5914 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); 6070 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
5915 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); 6071 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
5916 __ mov(tmp3, tmp1); 6072 __ mov(tmp3, tmp1);
5917 STATIC_ASSERT(kNotStringTag != 0); 6073 STATIC_ASSERT(kNotStringTag != 0);
5918 __ or_(tmp3, Operand(tmp2)); 6074 __ or_(tmp3, Operand(tmp2));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
5963 __ bind(&miss); 6119 __ bind(&miss);
5964 GenerateMiss(masm); 6120 GenerateMiss(masm);
5965 } 6121 }
5966 6122
5967 6123
5968 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 6124 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
5969 ASSERT(state_ == CompareIC::OBJECTS); 6125 ASSERT(state_ == CompareIC::OBJECTS);
5970 Label miss; 6126 Label miss;
5971 __ mov(ecx, Operand(edx)); 6127 __ mov(ecx, Operand(edx));
5972 __ and_(ecx, Operand(eax)); 6128 __ and_(ecx, Operand(eax));
5973 __ test(ecx, Immediate(kSmiTagMask)); 6129 __ JumpIfSmi(ecx, &miss, Label::kNear);
5974 __ j(zero, &miss, Label::kNear);
5975 6130
5976 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); 6131 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx);
5977 __ j(not_equal, &miss, Label::kNear); 6132 __ j(not_equal, &miss, Label::kNear);
5978 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); 6133 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
5979 __ j(not_equal, &miss, Label::kNear); 6134 __ j(not_equal, &miss, Label::kNear);
5980 6135
5981 ASSERT(GetCondition() == equal); 6136 ASSERT(GetCondition() == equal);
5982 __ sub(eax, Operand(edx)); 6137 __ sub(eax, Operand(edx));
5983 __ ret(0); 6138 __ ret(0);
5984 6139
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
6413 6568
6414 // Fall through when we need to inform the incremental marker. 6569 // Fall through when we need to inform the incremental marker.
6415 } 6570 }
6416 6571
6417 6572
6418 #undef __ 6573 #undef __
6419 6574
6420 } } // namespace v8::internal 6575 } } // namespace v8::internal
6421 6576
6422 #endif // V8_TARGET_ARCH_IA32 6577 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698