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

Side by Side Diff: src/arm/code-stubs-arm.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/arm/code-stubs-arm.h ('k') | src/arm/deoptimizer-arm.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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 __ ldr(scratch1, FieldMemOperand(operand, HeapObject::kMapOffset)); 62 __ ldr(scratch1, FieldMemOperand(operand, HeapObject::kMapOffset));
63 __ LoadRoot(scratch2, Heap::kHeapNumberMapRootIndex); 63 __ LoadRoot(scratch2, Heap::kHeapNumberMapRootIndex);
64 __ cmp(scratch1, scratch2); 64 __ cmp(scratch1, scratch2);
65 __ b(ne, not_a_heap_number); 65 __ b(ne, not_a_heap_number);
66 } 66 }
67 67
68 68
69 void ToNumberStub::Generate(MacroAssembler* masm) { 69 void ToNumberStub::Generate(MacroAssembler* masm) {
70 // The ToNumber stub takes one argument in eax. 70 // The ToNumber stub takes one argument in eax.
71 Label check_heap_number, call_builtin; 71 Label check_heap_number, call_builtin;
72 __ tst(r0, Operand(kSmiTagMask)); 72 __ JumpIfNotSmi(r0, &check_heap_number);
73 __ b(ne, &check_heap_number);
74 __ Ret(); 73 __ Ret();
75 74
76 __ bind(&check_heap_number); 75 __ bind(&check_heap_number);
77 EmitCheckForHeapNumber(masm, r0, r1, ip, &call_builtin); 76 EmitCheckForHeapNumber(masm, r0, r1, ip, &call_builtin);
78 __ Ret(); 77 __ Ret();
79 78
80 __ bind(&call_builtin); 79 __ bind(&call_builtin);
81 __ push(r0); 80 __ push(r0);
82 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); 81 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
83 } 82 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 r0, 150 r0,
152 r1, 151 r1,
153 r2, 152 r2,
154 &gc, 153 &gc,
155 TAG_OBJECT); 154 TAG_OBJECT);
156 155
157 // Load the function from the stack. 156 // Load the function from the stack.
158 __ ldr(r3, MemOperand(sp, 0)); 157 __ ldr(r3, MemOperand(sp, 0));
159 158
160 // Setup the object header. 159 // Setup the object header.
161 __ LoadRoot(r2, Heap::kContextMapRootIndex); 160 __ LoadRoot(r2, Heap::kFunctionContextMapRootIndex);
162 __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 161 __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
163 __ mov(r2, Operand(Smi::FromInt(length))); 162 __ mov(r2, Operand(Smi::FromInt(length)));
164 __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset)); 163 __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset));
165 164
166 // Setup the fixed slots. 165 // Setup the fixed slots.
167 __ mov(r1, Operand(Smi::FromInt(0))); 166 __ mov(r1, Operand(Smi::FromInt(0)));
168 __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX))); 167 __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX)));
169 __ str(r0, MemOperand(r0, Context::SlotOffset(Context::FCONTEXT_INDEX))); 168 __ str(cp, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX)));
170 __ str(r1, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX)));
171 __ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX))); 169 __ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX)));
172 170
173 // Copy the global object from the surrounding context. 171 // Copy the global object from the previous context.
174 __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 172 __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
175 __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX))); 173 __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX)));
176 174
177 // Initialize the rest of the slots to undefined. 175 // Initialize the rest of the slots to undefined.
178 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 176 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
179 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { 177 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
180 __ str(r1, MemOperand(r0, Context::SlotOffset(i))); 178 __ str(r1, MemOperand(r0, Context::SlotOffset(i)));
181 } 179 }
182 180
183 // Remove the on-stack argument and return. 181 // Remove the on-stack argument and return.
184 __ mov(cp, r0); 182 __ mov(cp, r0);
185 __ pop(); 183 __ pop();
186 __ Ret(); 184 __ Ret();
187 185
188 // Need to collect. Call into runtime system. 186 // Need to collect. Call into runtime system.
189 __ bind(&gc); 187 __ bind(&gc);
190 __ TailCallRuntime(Runtime::kNewContext, 1, 1); 188 __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
191 } 189 }
192 190
193 191
194 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { 192 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
195 // Stack layout on entry: 193 // Stack layout on entry:
196 // 194 //
197 // [sp]: constant elements. 195 // [sp]: constant elements.
198 // [sp + kPointerSize]: literal index. 196 // [sp + kPointerSize]: literal index.
199 // [sp + (2 * kPointerSize)]: literals array. 197 // [sp + (2 * kPointerSize)]: literals array.
200 198
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 Major MajorKey() { return ConvertToDouble; } 297 Major MajorKey() { return ConvertToDouble; }
300 int MinorKey() { 298 int MinorKey() {
301 // Encode the parameters in a unique 16 bit value. 299 // Encode the parameters in a unique 16 bit value.
302 return result1_.code() + 300 return result1_.code() +
303 (result2_.code() << 4) + 301 (result2_.code() << 4) +
304 (source_.code() << 8) + 302 (source_.code() << 8) +
305 (zeros_.code() << 12); 303 (zeros_.code() << 12);
306 } 304 }
307 305
308 void Generate(MacroAssembler* masm); 306 void Generate(MacroAssembler* masm);
309
310 const char* GetName() { return "ConvertToDoubleStub"; }
311
312 #ifdef DEBUG
313 void Print() { PrintF("ConvertToDoubleStub\n"); }
314 #endif
315 }; 307 };
316 308
317 309
318 void ConvertToDoubleStub::Generate(MacroAssembler* masm) { 310 void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
319 Register exponent = result1_; 311 Register exponent = result1_;
320 Register mantissa = result2_; 312 Register mantissa = result2_;
321 313
322 Label not_special; 314 Label not_special;
323 // Convert from Smi to integer. 315 // Convert from Smi to integer.
324 __ mov(source_, Operand(source_, ASR, kSmiTagSize)); 316 __ mov(source_, Operand(source_, ASR, kSmiTagSize));
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 if (destination == kCoreRegisters) { 379 if (destination == kCoreRegisters) {
388 __ vmov(r2, r3, d7); 380 __ vmov(r2, r3, d7);
389 __ vmov(r0, r1, d6); 381 __ vmov(r0, r1, d6);
390 } 382 }
391 } else { 383 } else {
392 ASSERT(destination == kCoreRegisters); 384 ASSERT(destination == kCoreRegisters);
393 // Write Smi from r0 to r3 and r2 in double format. 385 // Write Smi from r0 to r3 and r2 in double format.
394 __ mov(scratch1, Operand(r0)); 386 __ mov(scratch1, Operand(r0));
395 ConvertToDoubleStub stub1(r3, r2, scratch1, scratch2); 387 ConvertToDoubleStub stub1(r3, r2, scratch1, scratch2);
396 __ push(lr); 388 __ push(lr);
397 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET); 389 __ Call(stub1.GetCode());
398 // Write Smi from r1 to r1 and r0 in double format. 390 // Write Smi from r1 to r1 and r0 in double format.
399 __ mov(scratch1, Operand(r1)); 391 __ mov(scratch1, Operand(r1));
400 ConvertToDoubleStub stub2(r1, r0, scratch1, scratch2); 392 ConvertToDoubleStub stub2(r1, r0, scratch1, scratch2);
401 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); 393 __ Call(stub2.GetCode());
402 __ pop(lr); 394 __ pop(lr);
403 } 395 }
404 } 396 }
405 397
406 398
407 void FloatingPointHelper::LoadOperands( 399 void FloatingPointHelper::LoadOperands(
408 MacroAssembler* masm, 400 MacroAssembler* masm,
409 FloatingPointHelper::Destination destination, 401 FloatingPointHelper::Destination destination,
410 Register heap_number_map, 402 Register heap_number_map,
411 Register scratch1, 403 Register scratch1,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 if (destination == kCoreRegisters) { 460 if (destination == kCoreRegisters) {
469 // Load the converted smi to dst1 and dst2 in double format. 461 // Load the converted smi to dst1 and dst2 in double format.
470 __ vmov(dst1, dst2, dst); 462 __ vmov(dst1, dst2, dst);
471 } 463 }
472 } else { 464 } else {
473 ASSERT(destination == kCoreRegisters); 465 ASSERT(destination == kCoreRegisters);
474 // Write smi to dst1 and dst2 double format. 466 // Write smi to dst1 and dst2 double format.
475 __ mov(scratch1, Operand(object)); 467 __ mov(scratch1, Operand(object));
476 ConvertToDoubleStub stub(dst2, dst1, scratch1, scratch2); 468 ConvertToDoubleStub stub(dst2, dst1, scratch1, scratch2);
477 __ push(lr); 469 __ push(lr);
478 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); 470 __ Call(stub.GetCode());
479 __ pop(lr); 471 __ pop(lr);
480 } 472 }
481 473
482 __ bind(&done); 474 __ bind(&done);
483 } 475 }
484 476
485 477
486 void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm, 478 void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
487 Register object, 479 Register object,
488 Register dst, 480 Register dst,
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 __ b(ne, &not_identical); 916 __ b(ne, &not_identical);
925 917
926 // The two objects are identical. If we know that one of them isn't NaN then 918 // The two objects are identical. If we know that one of them isn't NaN then
927 // we now know they test equal. 919 // we now know they test equal.
928 if (cond != eq || !never_nan_nan) { 920 if (cond != eq || !never_nan_nan) {
929 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(), 921 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
930 // so we do the second best thing - test it ourselves. 922 // so we do the second best thing - test it ourselves.
931 // They are both equal and they are not both Smis so both of them are not 923 // They are both equal and they are not both Smis so both of them are not
932 // Smis. If it's not a heap number, then return equal. 924 // Smis. If it's not a heap number, then return equal.
933 if (cond == lt || cond == gt) { 925 if (cond == lt || cond == gt) {
934 __ CompareObjectType(r0, r4, r4, FIRST_JS_OBJECT_TYPE); 926 __ CompareObjectType(r0, r4, r4, FIRST_SPEC_OBJECT_TYPE);
935 __ b(ge, slow); 927 __ b(ge, slow);
936 } else { 928 } else {
937 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); 929 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
938 __ b(eq, &heap_number); 930 __ b(eq, &heap_number);
939 // Comparing JS objects with <=, >= is complicated. 931 // Comparing JS objects with <=, >= is complicated.
940 if (cond != eq) { 932 if (cond != eq) {
941 __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE)); 933 __ cmp(r4, Operand(FIRST_SPEC_OBJECT_TYPE));
942 __ b(ge, slow); 934 __ b(ge, slow);
943 // Normally here we fall through to return_equal, but undefined is 935 // Normally here we fall through to return_equal, but undefined is
944 // special: (undefined == undefined) == true, but 936 // special: (undefined == undefined) == true, but
945 // (undefined <= undefined) == false! See ECMAScript 11.8.5. 937 // (undefined <= undefined) == false! See ECMAScript 11.8.5.
946 if (cond == le || cond == ge) { 938 if (cond == le || cond == ge) {
947 __ cmp(r4, Operand(ODDBALL_TYPE)); 939 __ cmp(r4, Operand(ODDBALL_TYPE));
948 __ b(ne, &return_equal); 940 __ b(ne, &return_equal);
949 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 941 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
950 __ cmp(r0, r2); 942 __ cmp(r0, r2);
951 __ b(ne, &return_equal); 943 __ b(ne, &return_equal);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 static void EmitSmiNonsmiComparison(MacroAssembler* masm, 1014 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
1023 Register lhs, 1015 Register lhs,
1024 Register rhs, 1016 Register rhs,
1025 Label* lhs_not_nan, 1017 Label* lhs_not_nan,
1026 Label* slow, 1018 Label* slow,
1027 bool strict) { 1019 bool strict) {
1028 ASSERT((lhs.is(r0) && rhs.is(r1)) || 1020 ASSERT((lhs.is(r0) && rhs.is(r1)) ||
1029 (lhs.is(r1) && rhs.is(r0))); 1021 (lhs.is(r1) && rhs.is(r0)));
1030 1022
1031 Label rhs_is_smi; 1023 Label rhs_is_smi;
1032 __ tst(rhs, Operand(kSmiTagMask)); 1024 __ JumpIfSmi(rhs, &rhs_is_smi);
1033 __ b(eq, &rhs_is_smi);
1034 1025
1035 // Lhs is a Smi. Check whether the rhs is a heap number. 1026 // Lhs is a Smi. Check whether the rhs is a heap number.
1036 __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE); 1027 __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE);
1037 if (strict) { 1028 if (strict) {
1038 // If rhs is not a number and lhs is a Smi then strict equality cannot 1029 // If rhs is not a number and lhs is a Smi then strict equality cannot
1039 // succeed. Return non-equal 1030 // succeed. Return non-equal
1040 // If rhs is r0 then there is already a non zero value in it. 1031 // If rhs is r0 then there is already a non zero value in it.
1041 if (!rhs.is(r0)) { 1032 if (!rhs.is(r0)) {
1042 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); 1033 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
1043 } 1034 }
(...skipping 10 matching lines...) Expand all
1054 CpuFeatures::Scope scope(VFP3); 1045 CpuFeatures::Scope scope(VFP3);
1055 __ SmiToDoubleVFPRegister(lhs, d7, r7, s15); 1046 __ SmiToDoubleVFPRegister(lhs, d7, r7, s15);
1056 // Load the double from rhs, tagged HeapNumber r0, to d6. 1047 // Load the double from rhs, tagged HeapNumber r0, to d6.
1057 __ sub(r7, rhs, Operand(kHeapObjectTag)); 1048 __ sub(r7, rhs, Operand(kHeapObjectTag));
1058 __ vldr(d6, r7, HeapNumber::kValueOffset); 1049 __ vldr(d6, r7, HeapNumber::kValueOffset);
1059 } else { 1050 } else {
1060 __ push(lr); 1051 __ push(lr);
1061 // Convert lhs to a double in r2, r3. 1052 // Convert lhs to a double in r2, r3.
1062 __ mov(r7, Operand(lhs)); 1053 __ mov(r7, Operand(lhs));
1063 ConvertToDoubleStub stub1(r3, r2, r7, r6); 1054 ConvertToDoubleStub stub1(r3, r2, r7, r6);
1064 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET); 1055 __ Call(stub1.GetCode());
1065 // Load rhs to a double in r0, r1. 1056 // Load rhs to a double in r0, r1.
1066 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 1057 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset));
1067 __ pop(lr); 1058 __ pop(lr);
1068 } 1059 }
1069 1060
1070 // We now have both loaded as doubles but we can skip the lhs nan check 1061 // We now have both loaded as doubles but we can skip the lhs nan check
1071 // since it's a smi. 1062 // since it's a smi.
1072 __ jmp(lhs_not_nan); 1063 __ jmp(lhs_not_nan);
1073 1064
1074 __ bind(&rhs_is_smi); 1065 __ bind(&rhs_is_smi);
(...skipping 21 matching lines...) Expand all
1096 __ vldr(d7, r7, HeapNumber::kValueOffset); 1087 __ vldr(d7, r7, HeapNumber::kValueOffset);
1097 // Convert rhs to a double in d6 . 1088 // Convert rhs to a double in d6 .
1098 __ SmiToDoubleVFPRegister(rhs, d6, r7, s13); 1089 __ SmiToDoubleVFPRegister(rhs, d6, r7, s13);
1099 } else { 1090 } else {
1100 __ push(lr); 1091 __ push(lr);
1101 // Load lhs to a double in r2, r3. 1092 // Load lhs to a double in r2, r3.
1102 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 1093 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset));
1103 // Convert rhs to a double in r0, r1. 1094 // Convert rhs to a double in r0, r1.
1104 __ mov(r7, Operand(rhs)); 1095 __ mov(r7, Operand(rhs));
1105 ConvertToDoubleStub stub2(r1, r0, r7, r6); 1096 ConvertToDoubleStub stub2(r1, r0, r7, r6);
1106 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); 1097 __ Call(stub2.GetCode());
1107 __ pop(lr); 1098 __ pop(lr);
1108 } 1099 }
1109 // Fall through to both_loaded_as_doubles. 1100 // Fall through to both_loaded_as_doubles.
1110 } 1101 }
1111 1102
1112 1103
1113 void EmitNanCheck(MacroAssembler* masm, Label* lhs_not_nan, Condition cond) { 1104 void EmitNanCheck(MacroAssembler* masm, Label* lhs_not_nan, Condition cond) {
1114 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); 1105 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
1115 Register rhs_exponent = exp_first ? r0 : r1; 1106 Register rhs_exponent = exp_first ? r0 : r1;
1116 Register lhs_exponent = exp_first ? r2 : r3; 1107 Register lhs_exponent = exp_first ? r2 : r3;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 } 1204 }
1214 1205
1215 1206
1216 // See comment at call site. 1207 // See comment at call site.
1217 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 1208 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
1218 Register lhs, 1209 Register lhs,
1219 Register rhs) { 1210 Register rhs) {
1220 ASSERT((lhs.is(r0) && rhs.is(r1)) || 1211 ASSERT((lhs.is(r0) && rhs.is(r1)) ||
1221 (lhs.is(r1) && rhs.is(r0))); 1212 (lhs.is(r1) && rhs.is(r0)));
1222 1213
1223 // If either operand is a JSObject or an oddball value, then they are 1214 // If either operand is a JS object or an oddball value, then they are
1224 // not equal since their pointers are different. 1215 // not equal since their pointers are different.
1225 // There is no test for undetectability in strict equality. 1216 // There is no test for undetectability in strict equality.
1226 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1217 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
1227 Label first_non_object; 1218 Label first_non_object;
1228 // Get the type of the first operand into r2 and compare it with 1219 // Get the type of the first operand into r2 and compare it with
1229 // FIRST_JS_OBJECT_TYPE. 1220 // FIRST_SPEC_OBJECT_TYPE.
1230 __ CompareObjectType(rhs, r2, r2, FIRST_JS_OBJECT_TYPE); 1221 __ CompareObjectType(rhs, r2, r2, FIRST_SPEC_OBJECT_TYPE);
1231 __ b(lt, &first_non_object); 1222 __ b(lt, &first_non_object);
1232 1223
1233 // Return non-zero (r0 is not zero) 1224 // Return non-zero (r0 is not zero)
1234 Label return_not_equal; 1225 Label return_not_equal;
1235 __ bind(&return_not_equal); 1226 __ bind(&return_not_equal);
1236 __ Ret(); 1227 __ Ret();
1237 1228
1238 __ bind(&first_non_object); 1229 __ bind(&first_non_object);
1239 // Check for oddballs: true, false, null, undefined. 1230 // Check for oddballs: true, false, null, undefined.
1240 __ cmp(r2, Operand(ODDBALL_TYPE)); 1231 __ cmp(r2, Operand(ODDBALL_TYPE));
1241 __ b(eq, &return_not_equal); 1232 __ b(eq, &return_not_equal);
1242 1233
1243 __ CompareObjectType(lhs, r3, r3, FIRST_JS_OBJECT_TYPE); 1234 __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE);
1244 __ b(ge, &return_not_equal); 1235 __ b(ge, &return_not_equal);
1245 1236
1246 // Check for oddballs: true, false, null, undefined. 1237 // Check for oddballs: true, false, null, undefined.
1247 __ cmp(r3, Operand(ODDBALL_TYPE)); 1238 __ cmp(r3, Operand(ODDBALL_TYPE));
1248 __ b(eq, &return_not_equal); 1239 __ b(eq, &return_not_equal);
1249 1240
1250 // Now that we have the types we might as well check for symbol-symbol. 1241 // Now that we have the types we might as well check for symbol-symbol.
1251 // Ensure that no non-strings have the symbol bit set. 1242 // Ensure that no non-strings have the symbol bit set.
1252 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask); 1243 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask);
1253 STATIC_ASSERT(kSymbolTag != 0); 1244 STATIC_ASSERT(kSymbolTag != 0);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1310 __ b(ge, not_both_strings); 1301 __ b(ge, not_both_strings);
1311 __ tst(r3, Operand(kIsSymbolMask)); 1302 __ tst(r3, Operand(kIsSymbolMask));
1312 __ b(eq, possible_strings); 1303 __ b(eq, possible_strings);
1313 1304
1314 // Both are symbols. We already checked they weren't the same pointer 1305 // Both are symbols. We already checked they weren't the same pointer
1315 // so they are not equal. 1306 // so they are not equal.
1316 __ mov(r0, Operand(NOT_EQUAL)); 1307 __ mov(r0, Operand(NOT_EQUAL));
1317 __ Ret(); 1308 __ Ret();
1318 1309
1319 __ bind(&object_test); 1310 __ bind(&object_test);
1320 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); 1311 __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE));
1321 __ b(lt, not_both_strings); 1312 __ b(lt, not_both_strings);
1322 __ CompareObjectType(lhs, r2, r3, FIRST_JS_OBJECT_TYPE); 1313 __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE);
1323 __ b(lt, not_both_strings); 1314 __ b(lt, not_both_strings);
1324 // If both objects are undetectable, they are equal. Otherwise, they 1315 // If both objects are undetectable, they are equal. Otherwise, they
1325 // are not equal, since they are different objects and an object is not 1316 // are not equal, since they are different objects and an object is not
1326 // equal to undefined. 1317 // equal to undefined.
1327 __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset)); 1318 __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset));
1328 __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset)); 1319 __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset));
1329 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); 1320 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
1330 __ and_(r0, r2, Operand(r3)); 1321 __ and_(r0, r2, Operand(r3));
1331 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); 1322 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
1332 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); 1323 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable));
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 void CompareStub::Generate(MacroAssembler* masm) { 1442 void CompareStub::Generate(MacroAssembler* masm) {
1452 ASSERT((lhs_.is(r0) && rhs_.is(r1)) || 1443 ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
1453 (lhs_.is(r1) && rhs_.is(r0))); 1444 (lhs_.is(r1) && rhs_.is(r0)));
1454 1445
1455 Label slow; // Call builtin. 1446 Label slow; // Call builtin.
1456 Label not_smis, both_loaded_as_doubles, lhs_not_nan; 1447 Label not_smis, both_loaded_as_doubles, lhs_not_nan;
1457 1448
1458 if (include_smi_compare_) { 1449 if (include_smi_compare_) {
1459 Label not_two_smis, smi_done; 1450 Label not_two_smis, smi_done;
1460 __ orr(r2, r1, r0); 1451 __ orr(r2, r1, r0);
1461 __ tst(r2, Operand(kSmiTagMask)); 1452 __ JumpIfNotSmi(r2, &not_two_smis);
1462 __ b(ne, &not_two_smis);
1463 __ mov(r1, Operand(r1, ASR, 1)); 1453 __ mov(r1, Operand(r1, ASR, 1));
1464 __ sub(r0, r1, Operand(r0, ASR, 1)); 1454 __ sub(r0, r1, Operand(r0, ASR, 1));
1465 __ Ret(); 1455 __ Ret();
1466 __ bind(&not_two_smis); 1456 __ bind(&not_two_smis);
1467 } else if (FLAG_debug_code) { 1457 } else if (FLAG_debug_code) {
1468 __ orr(r2, r1, r0); 1458 __ orr(r2, r1, r0);
1469 __ tst(r2, Operand(kSmiTagMask)); 1459 __ tst(r2, Operand(kSmiTagMask));
1470 __ Assert(ne, "CompareStub: unexpected smi operands."); 1460 __ Assert(ne, "CompareStub: unexpected smi operands.");
1471 } 1461 }
1472 1462
1473 // NOTICE! This code is only reached after a smi-fast-case check, so 1463 // NOTICE! This code is only reached after a smi-fast-case check, so
1474 // it is certain that at least one operand isn't a smi. 1464 // it is certain that at least one operand isn't a smi.
1475 1465
1476 // Handle the case where the objects are identical. Either returns the answer 1466 // Handle the case where the objects are identical. Either returns the answer
1477 // or goes to slow. Only falls through if the objects were not identical. 1467 // or goes to slow. Only falls through if the objects were not identical.
1478 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); 1468 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
1479 1469
1480 // If either is a Smi (we know that not both are), then they can only 1470 // If either is a Smi (we know that not both are), then they can only
1481 // be strictly equal if the other is a HeapNumber. 1471 // be strictly equal if the other is a HeapNumber.
1482 STATIC_ASSERT(kSmiTag == 0); 1472 STATIC_ASSERT(kSmiTag == 0);
1483 ASSERT_EQ(0, Smi::FromInt(0)); 1473 ASSERT_EQ(0, Smi::FromInt(0));
1484 __ and_(r2, lhs_, Operand(rhs_)); 1474 __ and_(r2, lhs_, Operand(rhs_));
1485 __ tst(r2, Operand(kSmiTagMask)); 1475 __ JumpIfNotSmi(r2, &not_smis);
1486 __ b(ne, &not_smis);
1487 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 1476 // One operand is a smi. EmitSmiNonsmiComparison generates code that can:
1488 // 1) Return the answer. 1477 // 1) Return the answer.
1489 // 2) Go to slow. 1478 // 2) Go to slow.
1490 // 3) Fall through to both_loaded_as_doubles. 1479 // 3) Fall through to both_loaded_as_doubles.
1491 // 4) Jump to lhs_not_nan. 1480 // 4) Jump to lhs_not_nan.
1492 // In cases 3 and 4 we have found out we were dealing with a number-number 1481 // In cases 3 and 4 we have found out we were dealing with a number-number
1493 // comparison. If VFP3 is supported the double values of the numbers have 1482 // comparison. If VFP3 is supported the double values of the numbers have
1494 // been loaded into d7 and d6. Otherwise, the double values have been loaded 1483 // been loaded into d7 and d6. Otherwise, the double values have been loaded
1495 // into r0, r1, r2, and r3. 1484 // into r0, r1, r2, and r3.
1496 EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_); 1485 EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1607 __ mov(r0, Operand(Smi::FromInt(ncr))); 1596 __ mov(r0, Operand(Smi::FromInt(ncr)));
1608 __ push(r0); 1597 __ push(r0);
1609 } 1598 }
1610 1599
1611 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 1600 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
1612 // tagged as a small integer. 1601 // tagged as a small integer.
1613 __ InvokeBuiltin(native, JUMP_FUNCTION); 1602 __ InvokeBuiltin(native, JUMP_FUNCTION);
1614 } 1603 }
1615 1604
1616 1605
1617 // This stub does not handle the inlined cases (Smis, Booleans, undefined).
1618 // The stub returns zero for false, and a non-zero value for true. 1606 // The stub returns zero for false, and a non-zero value for true.
1619 void ToBooleanStub::Generate(MacroAssembler* masm) { 1607 void ToBooleanStub::Generate(MacroAssembler* masm) {
1620 // This stub uses VFP3 instructions. 1608 // This stub uses VFP3 instructions.
1621 CpuFeatures::Scope scope(VFP3); 1609 CpuFeatures::Scope scope(VFP3);
1622 1610
1623 Label false_result; 1611 Label false_result, true_result, not_string;
1624 Label not_heap_number; 1612 const Register map = r9.is(tos_) ? r7 : r9;
1625 Register scratch = r9.is(tos_) ? r7 : r9;
1626 1613
1627 // undefined -> false 1614 // undefined -> false
1628 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1615 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1629 __ cmp(tos_, ip); 1616 __ cmp(tos_, ip);
1630 __ b(eq, &false_result); 1617 __ b(eq, &false_result);
1631 1618
1632 // Boolean -> its value 1619 // Boolean -> its value
1633 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 1620 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1634 __ cmp(tos_, ip); 1621 __ cmp(tos_, ip);
1635 __ b(eq, &false_result); 1622 __ b(eq, &false_result);
1636 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1623 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1637 __ cmp(tos_, ip); 1624 __ cmp(tos_, ip);
1638 // "tos_" is a register and contains a non-zero value. Hence we implicitly 1625 // "tos_" is a register and contains a non-zero value. Hence we implicitly
1639 // return true if the equal condition is satisfied. 1626 // return true if the equal condition is satisfied.
1640 __ Ret(eq); 1627 __ Ret(eq);
1641 1628
1642 // Smis: 0 -> false, all other -> true 1629 // Smis: 0 -> false, all other -> true
1643 __ tst(tos_, tos_); 1630 __ tst(tos_, tos_);
1644 __ b(eq, &false_result); 1631 __ b(eq, &false_result);
1645 __ tst(tos_, Operand(kSmiTagMask)); 1632 __ tst(tos_, Operand(kSmiTagMask));
1646 // "tos_" is a register and contains a non-zero value. Hence we implicitly 1633 // "tos_" is a register and contains a non-zero value. Hence we implicitly
1647 // return true if the not equal condition is satisfied. 1634 // return true if the not equal condition is satisfied.
1648 __ Ret(eq); 1635 __ Ret(eq);
1649 1636
1650 // 'null' -> false 1637 // 'null' -> false
1651 __ LoadRoot(ip, Heap::kNullValueRootIndex); 1638 __ LoadRoot(ip, Heap::kNullValueRootIndex);
1652 __ cmp(tos_, ip); 1639 __ cmp(tos_, ip);
1653 __ b(eq, &false_result); 1640 __ b(eq, &false_result);
1654 1641
1655 // HeapNumber => false iff +0, -0, or NaN. 1642 // Get the map of the heap object.
1656 __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset)); 1643 __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
1657 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 1644
1658 __ cmp(scratch, ip); 1645 // Undetectable -> false.
1659 __ b(&not_heap_number, ne); 1646 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
1647 __ tst(ip, Operand(1 << Map::kIsUndetectable));
1648 __ b(&false_result, ne);
1649
1650 // JavaScript object -> true.
1651 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
1652 // "tos_" is a register and contains a non-zero value. Hence we implicitly
1653 // return true if the greater than condition is satisfied.
1654 __ Ret(ge);
1655
1656 // String value -> false iff empty.
1657 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
1658 __ b(&not_string, ge);
1659 __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset));
1660 // Return string length as boolean value, i.e. return false iff length is 0.
1661 __ Ret();
1662
1663 __ bind(&not_string);
1664 // HeapNumber -> false iff +0, -0, or NaN.
1665 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
1666 __ b(&true_result, ne);
1660 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); 1667 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
1661 __ VFPCompareAndSetFlags(d1, 0.0); 1668 __ VFPCompareAndSetFlags(d1, 0.0);
1662 // "tos_" is a register, and contains a non zero value by default. 1669 // "tos_" is a register, and contains a non zero value by default.
1663 // Hence we only need to overwrite "tos_" with zero to return false for 1670 // Hence we only need to overwrite "tos_" with zero to return false for
1664 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. 1671 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
1665 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); // for FP_ZERO 1672 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); // for FP_ZERO
1666 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs); // for FP_NAN 1673 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs); // for FP_NAN
1667 __ Ret(); 1674 __ Ret();
1668 1675
1669 __ bind(&not_heap_number); 1676 // Return 1/0 for true/false in tos_.
1670 1677 __ bind(&true_result);
1671 // It can be an undetectable object. 1678 __ mov(tos_, Operand(1, RelocInfo::NONE));
1672 // Undetectable => false.
1673 __ ldr(ip, FieldMemOperand(tos_, HeapObject::kMapOffset));
1674 __ ldrb(scratch, FieldMemOperand(ip, Map::kBitFieldOffset));
1675 __ and_(scratch, scratch, Operand(1 << Map::kIsUndetectable));
1676 __ cmp(scratch, Operand(1 << Map::kIsUndetectable));
1677 __ b(&false_result, eq);
1678
1679 // JavaScript object => true.
1680 __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset));
1681 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1682 __ cmp(scratch, Operand(FIRST_JS_OBJECT_TYPE));
1683 // "tos_" is a register and contains a non-zero value.
1684 // Hence we implicitly return true if the greater than
1685 // condition is satisfied.
1686 __ Ret(gt);
1687
1688 // Check for string
1689 __ ldr(scratch, FieldMemOperand(tos_, HeapObject::kMapOffset));
1690 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1691 __ cmp(scratch, Operand(FIRST_NONSTRING_TYPE));
1692 // "tos_" is a register and contains a non-zero value.
1693 // Hence we implicitly return true if the greater than
1694 // condition is satisfied.
1695 __ Ret(gt);
1696
1697 // String value => false iff empty, i.e., length is zero
1698 __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset));
1699 // If length is zero, "tos_" contains zero ==> false.
1700 // If length is not zero, "tos_" contains a non-zero value ==> true.
1701 __ Ret(); 1679 __ Ret();
1702
1703 // Return 0 in "tos_" for false .
1704 __ bind(&false_result); 1680 __ bind(&false_result);
1705 __ mov(tos_, Operand(0, RelocInfo::NONE)); 1681 __ mov(tos_, Operand(0, RelocInfo::NONE));
1706 __ Ret(); 1682 __ Ret();
1707 } 1683 }
1708 1684
1709 1685
1710 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 1686 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
1711 // We don't allow a GC during a store buffer overflow so there is no need to 1687 // We don't allow a GC during a store buffer overflow so there is no need to
1712 // store the registers in any particular way, but we do have to store and 1688 // store the registers in any particular way, but we do have to store and
1713 // restore them. 1689 // restore them.
(...skipping 19 matching lines...) Expand all
1733 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { 1709 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) {
1734 DwVfpRegister reg = DwVfpRegister::from_code(i); 1710 DwVfpRegister reg = DwVfpRegister::from_code(i);
1735 __ vldr(reg, MemOperand(sp, i * kDoubleSize)); 1711 __ vldr(reg, MemOperand(sp, i * kDoubleSize));
1736 } 1712 }
1737 __ add(sp, sp, Operand(kDoubleSize * DwVfpRegister::kNumRegisters)); 1713 __ add(sp, sp, Operand(kDoubleSize * DwVfpRegister::kNumRegisters));
1738 } 1714 }
1739 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). 1715 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0).
1740 } 1716 }
1741 1717
1742 1718
1743 Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
1744 UnaryOpStub stub(key, type_info);
1745 return stub.GetCode();
1746 }
1747
1748
1749 const char* UnaryOpStub::GetName() { 1719 const char* UnaryOpStub::GetName() {
1750 if (name_ != NULL) return name_; 1720 if (name_ != NULL) return name_;
1751 const int kMaxNameLength = 100; 1721 const int kMaxNameLength = 100;
1752 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( 1722 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
1753 kMaxNameLength); 1723 kMaxNameLength);
1754 if (name_ == NULL) return "OOM"; 1724 if (name_ == NULL) return "OOM";
1755 const char* op_name = Token::Name(op_); 1725 const char* op_name = Token::Name(op_);
1756 const char* overwrite_name = NULL; // Make g++ happy. 1726 const char* overwrite_name = NULL; // Make g++ happy.
1757 switch (mode_) { 1727 switch (mode_) {
1758 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; 1728 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
(...skipping 22 matching lines...) Expand all
1781 GenerateHeapNumberStub(masm); 1751 GenerateHeapNumberStub(masm);
1782 break; 1752 break;
1783 case UnaryOpIC::GENERIC: 1753 case UnaryOpIC::GENERIC:
1784 GenerateGenericStub(masm); 1754 GenerateGenericStub(masm);
1785 break; 1755 break;
1786 } 1756 }
1787 } 1757 }
1788 1758
1789 1759
1790 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 1760 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
1791 // Prepare to push argument. 1761 __ mov(r3, Operand(r0)); // the operand
1792 __ mov(r3, Operand(r0)); 1762 __ mov(r2, Operand(Smi::FromInt(op_)));
1793 1763 __ mov(r1, Operand(Smi::FromInt(mode_)));
1794 // Push this stub's key. Although the operation and the type info are
1795 // encoded into the key, the encoding is opaque, so push them too.
1796 __ mov(r2, Operand(Smi::FromInt(MinorKey())));
1797 __ mov(r1, Operand(Smi::FromInt(op_)));
1798 __ mov(r0, Operand(Smi::FromInt(operand_type_))); 1764 __ mov(r0, Operand(Smi::FromInt(operand_type_)));
1799
1800 __ Push(r3, r2, r1, r0); 1765 __ Push(r3, r2, r1, r0);
1801 1766
1802 __ TailCallExternalReference( 1767 __ TailCallExternalReference(
1803 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), 1768 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
1804 masm->isolate()),
1805 4,
1806 1);
1807 } 1769 }
1808 1770
1809 1771
1810 // TODO(svenpanne): Use virtual functions instead of switch. 1772 // TODO(svenpanne): Use virtual functions instead of switch.
1811 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 1773 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1812 switch (op_) { 1774 switch (op_) {
1813 case Token::SUB: 1775 case Token::SUB:
1814 GenerateSmiStubSub(masm); 1776 GenerateSmiStubSub(masm);
1815 break; 1777 break;
1816 case Token::BIT_NOT: 1778 case Token::BIT_NOT:
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
2045 break; 2007 break;
2046 case Token::BIT_NOT: 2008 case Token::BIT_NOT:
2047 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); 2009 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
2048 break; 2010 break;
2049 default: 2011 default:
2050 UNREACHABLE(); 2012 UNREACHABLE();
2051 } 2013 }
2052 } 2014 }
2053 2015
2054 2016
2055 Handle<Code> GetBinaryOpStub(int key,
2056 BinaryOpIC::TypeInfo type_info,
2057 BinaryOpIC::TypeInfo result_type_info) {
2058 BinaryOpStub stub(key, type_info, result_type_info);
2059 return stub.GetCode();
2060 }
2061
2062
2063 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 2017 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
2064 Label get_result; 2018 Label get_result;
2065 2019
2066 __ Push(r1, r0); 2020 __ Push(r1, r0);
2067 2021
2068 __ mov(r2, Operand(Smi::FromInt(MinorKey()))); 2022 __ mov(r2, Operand(Smi::FromInt(MinorKey())));
2069 __ mov(r1, Operand(Smi::FromInt(op_))); 2023 __ mov(r1, Operand(Smi::FromInt(op_)));
2070 __ mov(r0, Operand(Smi::FromInt(operands_type_))); 2024 __ mov(r0, Operand(Smi::FromInt(operands_type_)));
2071 __ Push(r2, r1, r0); 2025 __ Push(r2, r1, r0);
2072 2026
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
2487 Label not_smis; 2441 Label not_smis;
2488 2442
2489 Register left = r1; 2443 Register left = r1;
2490 Register right = r0; 2444 Register right = r0;
2491 Register scratch1 = r7; 2445 Register scratch1 = r7;
2492 Register scratch2 = r9; 2446 Register scratch2 = r9;
2493 2447
2494 // Perform combined smi check on both operands. 2448 // Perform combined smi check on both operands.
2495 __ orr(scratch1, left, Operand(right)); 2449 __ orr(scratch1, left, Operand(right));
2496 STATIC_ASSERT(kSmiTag == 0); 2450 STATIC_ASSERT(kSmiTag == 0);
2497 __ tst(scratch1, Operand(kSmiTagMask)); 2451 __ JumpIfNotSmi(scratch1, &not_smis);
2498 __ b(ne, &not_smis);
2499 2452
2500 // If the smi-smi operation results in a smi return is generated. 2453 // If the smi-smi operation results in a smi return is generated.
2501 GenerateSmiSmiOperation(masm); 2454 GenerateSmiSmiOperation(masm);
2502 2455
2503 // If heap number results are possible generate the result in an allocated 2456 // If heap number results are possible generate the result in an allocated
2504 // heap number. 2457 // heap number.
2505 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { 2458 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) {
2506 GenerateFPOperation(masm, true, use_runtime, gc_required); 2459 GenerateFPOperation(masm, true, use_runtime, gc_required);
2507 } 2460 }
2508 __ bind(&not_smis); 2461 __ bind(&not_smis);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
2601 GenerateSmiSmiOperation(masm); 2554 GenerateSmiSmiOperation(masm);
2602 // Fall through if the result is not a smi. 2555 // Fall through if the result is not a smi.
2603 __ bind(&skip); 2556 __ bind(&skip);
2604 2557
2605 switch (op_) { 2558 switch (op_) {
2606 case Token::ADD: 2559 case Token::ADD:
2607 case Token::SUB: 2560 case Token::SUB:
2608 case Token::MUL: 2561 case Token::MUL:
2609 case Token::DIV: 2562 case Token::DIV:
2610 case Token::MOD: { 2563 case Token::MOD: {
2611 // Load both operands and check that they are 32-bit integer. 2564 // Load both operands and check that they are 32-bit integer.
2612 // Jump to type transition if they are not. The registers r0 and r1 (right 2565 // Jump to type transition if they are not. The registers r0 and r1 (right
2613 // and left) are preserved for the runtime call. 2566 // and left) are preserved for the runtime call.
2614 FloatingPointHelper::Destination destination = 2567 FloatingPointHelper::Destination destination =
2615 CpuFeatures::IsSupported(VFP3) && 2568 (CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD)
2616 op_ != Token::MOD ? 2569 ? FloatingPointHelper::kVFPRegisters
2617 FloatingPointHelper::kVFPRegisters : 2570 : FloatingPointHelper::kCoreRegisters;
2618 FloatingPointHelper::kCoreRegisters;
2619 2571
2620 FloatingPointHelper::LoadNumberAsInt32Double(masm, 2572 FloatingPointHelper::LoadNumberAsInt32Double(masm,
2621 right, 2573 right,
2622 destination, 2574 destination,
2623 d7, 2575 d7,
2624 r2, 2576 r2,
2625 r3, 2577 r3,
2626 heap_number_map, 2578 heap_number_map,
2627 scratch1, 2579 scratch1,
2628 scratch2, 2580 scratch2,
2629 s0, 2581 s0,
2630 &transition); 2582 &transition);
2631 FloatingPointHelper::LoadNumberAsInt32Double(masm, 2583 FloatingPointHelper::LoadNumberAsInt32Double(masm,
2632 left, 2584 left,
2633 destination, 2585 destination,
2634 d6, 2586 d6,
2635 r4, 2587 r4,
2636 r5, 2588 r5,
2637 heap_number_map, 2589 heap_number_map,
2638 scratch1, 2590 scratch1,
2639 scratch2, 2591 scratch2,
2640 s0, 2592 s0,
2641 &transition); 2593 &transition);
2642 2594
2643 if (destination == FloatingPointHelper::kVFPRegisters) { 2595 if (destination == FloatingPointHelper::kVFPRegisters) {
2644 CpuFeatures::Scope scope(VFP3); 2596 CpuFeatures::Scope scope(VFP3);
2645 Label return_heap_number; 2597 Label return_heap_number;
2646 switch (op_) { 2598 switch (op_) {
2647 case Token::ADD: 2599 case Token::ADD:
2648 __ vadd(d5, d6, d7); 2600 __ vadd(d5, d6, d7);
2649 break; 2601 break;
2650 case Token::SUB: 2602 case Token::SUB:
2651 __ vsub(d5, d6, d7); 2603 __ vsub(d5, d6, d7);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2692 __ b(ne, &return_heap_number); 2644 __ b(ne, &return_heap_number);
2693 __ bind(&not_zero); 2645 __ bind(&not_zero);
2694 2646
2695 // Tag the result and return. 2647 // Tag the result and return.
2696 __ SmiTag(r0, scratch1); 2648 __ SmiTag(r0, scratch1);
2697 __ Ret(); 2649 __ Ret();
2698 } else { 2650 } else {
2699 // DIV just falls through to allocating a heap number. 2651 // DIV just falls through to allocating a heap number.
2700 } 2652 }
2701 2653
2702 if (result_type_ >= (op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER 2654 __ bind(&return_heap_number);
2703 : BinaryOpIC::INT32) { 2655 // Return a heap number, or fall through to type transition or runtime
2704 __ bind(&return_heap_number); 2656 // call if we can't.
2657 if (result_type_ >= ((op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER
2658 : BinaryOpIC::INT32)) {
2705 // We are using vfp registers so r5 is available. 2659 // We are using vfp registers so r5 is available.
2706 heap_number_result = r5; 2660 heap_number_result = r5;
2707 GenerateHeapResultAllocation(masm, 2661 GenerateHeapResultAllocation(masm,
2708 heap_number_result, 2662 heap_number_result,
2709 heap_number_map, 2663 heap_number_map,
2710 scratch1, 2664 scratch1,
2711 scratch2, 2665 scratch2,
2712 &call_runtime); 2666 &call_runtime);
2713 __ sub(r0, heap_number_result, Operand(kHeapObjectTag)); 2667 __ sub(r0, heap_number_result, Operand(kHeapObjectTag));
2714 __ vstr(d5, r0, HeapNumber::kValueOffset); 2668 __ vstr(d5, r0, HeapNumber::kValueOffset);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
2868 __ TailCallStub(&stub); 2822 __ TailCallStub(&stub);
2869 } 2823 }
2870 2824
2871 break; 2825 break;
2872 } 2826 }
2873 2827
2874 default: 2828 default:
2875 UNREACHABLE(); 2829 UNREACHABLE();
2876 } 2830 }
2877 2831
2878 if (transition.is_linked()) { 2832 // We never expect DIV to yield an integer result, so we always generate
2833 // type transition code for DIV operations expecting an integer result: the
2834 // code will fall through to this type transition.
2835 if (transition.is_linked() ||
2836 ((op_ == Token::DIV) && (result_type_ <= BinaryOpIC::INT32))) {
2879 __ bind(&transition); 2837 __ bind(&transition);
2880 GenerateTypeTransition(masm); 2838 GenerateTypeTransition(masm);
2881 } 2839 }
2882 2840
2883 __ bind(&call_runtime); 2841 __ bind(&call_runtime);
2884 GenerateCallRuntime(masm); 2842 GenerateCallRuntime(masm);
2885 } 2843 }
2886 2844
2887 2845
2888 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { 2846 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
3437 __ b(eq, &alignment_as_expected); 3395 __ b(eq, &alignment_as_expected);
3438 // Don't use Check here, as it will call Runtime_Abort re-entering here. 3396 // Don't use Check here, as it will call Runtime_Abort re-entering here.
3439 __ stop("Unexpected alignment"); 3397 __ stop("Unexpected alignment");
3440 __ bind(&alignment_as_expected); 3398 __ bind(&alignment_as_expected);
3441 } 3399 }
3442 } 3400 }
3443 #endif 3401 #endif
3444 3402
3445 __ mov(r2, Operand(ExternalReference::isolate_address())); 3403 __ mov(r2, Operand(ExternalReference::isolate_address()));
3446 3404
3447 3405 // To let the GC traverse the return address of the exit frames, we need to
3448 // TODO(1242173): To let the GC traverse the return address of the exit 3406 // know where the return address is. The CEntryStub is unmovable, so
3449 // frames, we need to know where the return address is. Right now, 3407 // we can store the address on the stack to be able to find it again and
3450 // we store it on the stack to be able to find it again, but we never 3408 // we never have to restore it, because it will not change.
3451 // restore from it in case of changes, which makes it impossible to
3452 // support moving the C entry code stub. This should be fixed, but currently
3453 // this is OK because the CEntryStub gets generated so early in the V8 boot
3454 // sequence that it is not moving ever.
3455
3456 // Compute the return address in lr to return to after the jump below. Pc is 3409 // Compute the return address in lr to return to after the jump below. Pc is
3457 // already at '+ 8' from the current instruction but return is after three 3410 // already at '+ 8' from the current instruction but return is after three
3458 // instructions so add another 4 to pc to get the return address. 3411 // instructions so add another 4 to pc to get the return address.
3459 masm->add(lr, pc, Operand(4)); 3412 masm->add(lr, pc, Operand(4));
3460 __ str(lr, MemOperand(sp, 0)); 3413 __ str(lr, MemOperand(sp, 0));
3461 masm->Jump(r5); 3414 masm->Jump(r5);
3462 3415
3463 if (always_allocate) { 3416 if (always_allocate) {
3464 // It's okay to clobber r2 and r3 here. Don't mess with r0 and r1 3417 // It's okay to clobber r2 and r3 here. Don't mess with r0 and r1
3465 // though (contain the result). 3418 // though (contain the result).
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
3595 // r3: argc 3548 // r3: argc
3596 // [sp+0]: argv 3549 // [sp+0]: argv
3597 3550
3598 Label invoke, exit; 3551 Label invoke, exit;
3599 3552
3600 // Called from C, so do not pop argc and args on exit (preserve sp) 3553 // Called from C, so do not pop argc and args on exit (preserve sp)
3601 // No need to save register-passed args 3554 // No need to save register-passed args
3602 // Save callee-saved registers (incl. cp and fp), sp, and lr 3555 // Save callee-saved registers (incl. cp and fp), sp, and lr
3603 __ stm(db_w, sp, kCalleeSaved | lr.bit()); 3556 __ stm(db_w, sp, kCalleeSaved | lr.bit());
3604 3557
3558 if (CpuFeatures::IsSupported(VFP3)) {
3559 CpuFeatures::Scope scope(VFP3);
3560 // Save callee-saved vfp registers.
3561 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
3562 // Set up the reserved register for 0.0.
3563 __ vmov(kDoubleRegZero, 0.0);
3564 }
3565
3605 // Get address of argv, see stm above. 3566 // Get address of argv, see stm above.
3606 // r0: code entry 3567 // r0: code entry
3607 // r1: function 3568 // r1: function
3608 // r2: receiver 3569 // r2: receiver
3609 // r3: argc 3570 // r3: argc
3610 __ ldr(r4, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize)); // argv 3571
3572 // Setup argv in r4.
3573 int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
3574 if (CpuFeatures::IsSupported(VFP3)) {
3575 offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize;
3576 }
3577 __ ldr(r4, MemOperand(sp, offset_to_argv));
3611 3578
3612 // Push a frame with special values setup to mark it as an entry frame. 3579 // Push a frame with special values setup to mark it as an entry frame.
3613 // r0: code entry 3580 // r0: code entry
3614 // r1: function 3581 // r1: function
3615 // r2: receiver 3582 // r2: receiver
3616 // r3: argc 3583 // r3: argc
3617 // r4: argv 3584 // r4: argv
3618 Isolate* isolate = masm->isolate(); 3585 Isolate* isolate = masm->isolate();
3619 __ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used. 3586 __ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used.
3620 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 3587 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
3725 3692
3726 // Reset the stack to the callee saved registers. 3693 // Reset the stack to the callee saved registers.
3727 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 3694 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
3728 3695
3729 // Restore callee-saved registers and return. 3696 // Restore callee-saved registers and return.
3730 #ifdef DEBUG 3697 #ifdef DEBUG
3731 if (FLAG_debug_code) { 3698 if (FLAG_debug_code) {
3732 __ mov(lr, Operand(pc)); 3699 __ mov(lr, Operand(pc));
3733 } 3700 }
3734 #endif 3701 #endif
3702
3703 if (CpuFeatures::IsSupported(VFP3)) {
3704 CpuFeatures::Scope scope(VFP3);
3705 // Restore callee-saved vfp registers.
3706 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
3707 }
3708
3735 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); 3709 __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
3736 } 3710 }
3737 3711
3738 3712
3739 // Uses registers r0 to r4. 3713 // Uses registers r0 to r4.
3740 // Expected input (depending on whether args are in registers or on the stack): 3714 // Expected input (depending on whether args are in registers or on the stack):
3741 // * object: r0 or at sp + 1 * kPointerSize. 3715 // * object: r0 or at sp + 1 * kPointerSize.
3742 // * function: r1 or at sp. 3716 // * function: r1 or at sp.
3743 // 3717 //
3744 // An inlined call site may have been generated before calling this stub. 3718 // An inlined call site may have been generated before calling this stub.
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
3964 __ Jump(lr); 3938 __ Jump(lr);
3965 3939
3966 // Slow-case: Handle non-smi or out-of-bounds access to arguments 3940 // Slow-case: Handle non-smi or out-of-bounds access to arguments
3967 // by calling the runtime system. 3941 // by calling the runtime system.
3968 __ bind(&slow); 3942 __ bind(&slow);
3969 __ push(r1); 3943 __ push(r1);
3970 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 3944 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
3971 } 3945 }
3972 3946
3973 3947
3974 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { 3948 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
3975 // sp[0] : number of parameters 3949 // sp[0] : number of parameters
3976 // sp[4] : receiver displacement 3950 // sp[4] : receiver displacement
3977 // sp[8] : function 3951 // sp[8] : function
3978 3952
3979 // Check if the calling frame is an arguments adaptor frame. 3953 // Check if the calling frame is an arguments adaptor frame.
3954 Label runtime;
3955 __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3956 __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset));
3957 __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3958 __ b(ne, &runtime);
3959
3960 // Patch the arguments.length and the parameters pointer in the current frame.
3961 __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
3962 __ str(r2, MemOperand(sp, 0 * kPointerSize));
3963 __ add(r3, r3, Operand(r2, LSL, 1));
3964 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
3965 __ str(r3, MemOperand(sp, 1 * kPointerSize));
3966
3967 __ bind(&runtime);
3968 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
3969 }
3970
3971
3972 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
3973 // Stack layout:
3974 // sp[0] : number of parameters (tagged)
3975 // sp[4] : address of receiver argument
3976 // sp[8] : function
3977 // Registers used over whole function:
3978 // r6 : allocated object (tagged)
3979 // r9 : mapped parameter count (tagged)
3980
3981 __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
3982 // r1 = parameter count (tagged)
3983
3984 // Check if the calling frame is an arguments adaptor frame.
3985 Label runtime;
3986 Label adaptor_frame, try_allocate;
3987 __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3988 __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset));
3989 __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3990 __ b(eq, &adaptor_frame);
3991
3992 // No adaptor, parameter count = argument count.
3993 __ mov(r2, r1);
3994 __ b(&try_allocate);
3995
3996 // We have an adaptor frame. Patch the parameters pointer.
3997 __ bind(&adaptor_frame);
3998 __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
3999 __ add(r3, r3, Operand(r2, LSL, 1));
4000 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
4001 __ str(r3, MemOperand(sp, 1 * kPointerSize));
4002
4003 // r1 = parameter count (tagged)
4004 // r2 = argument count (tagged)
4005 // Compute the mapped parameter count = min(r1, r2) in r1.
4006 __ cmp(r1, Operand(r2));
4007 __ mov(r1, Operand(r2), LeaveCC, gt);
4008
4009 __ bind(&try_allocate);
4010
4011 // Compute the sizes of backing store, parameter map, and arguments object.
4012 // 1. Parameter map, has 2 extra words containing context and backing store.
4013 const int kParameterMapHeaderSize =
4014 FixedArray::kHeaderSize + 2 * kPointerSize;
4015 // If there are no mapped parameters, we do not need the parameter_map.
4016 __ cmp(r1, Operand(Smi::FromInt(0)));
4017 __ mov(r9, Operand(0), LeaveCC, eq);
4018 __ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne);
4019 __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne);
4020
4021 // 2. Backing store.
4022 __ add(r9, r9, Operand(r2, LSL, 1));
4023 __ add(r9, r9, Operand(FixedArray::kHeaderSize));
4024
4025 // 3. Arguments object.
4026 __ add(r9, r9, Operand(Heap::kArgumentsObjectSize));
4027
4028 // Do the allocation of all three objects in one go.
4029 __ AllocateInNewSpace(r9, r0, r3, r4, &runtime, TAG_OBJECT);
4030
4031 // r0 = address of new object(s) (tagged)
4032 // r2 = argument count (tagged)
4033 // Get the arguments boilerplate from the current (global) context into r4.
4034 const int kNormalOffset =
4035 Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
4036 const int kAliasedOffset =
4037 Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX);
4038
4039 __ ldr(r4, MemOperand(r8, Context::SlotOffset(Context::GLOBAL_INDEX)));
4040 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset));
4041 __ cmp(r1, Operand(0));
4042 __ ldr(r4, MemOperand(r4, kNormalOffset), eq);
4043 __ ldr(r4, MemOperand(r4, kAliasedOffset), ne);
4044
4045 // r0 = address of new object (tagged)
4046 // r1 = mapped parameter count (tagged)
4047 // r2 = argument count (tagged)
4048 // r4 = address of boilerplate object (tagged)
4049 // Copy the JS object part.
4050 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
4051 __ ldr(r3, FieldMemOperand(r4, i));
4052 __ str(r3, FieldMemOperand(r0, i));
4053 }
4054
4055 // Setup the callee in-object property.
4056 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
4057 __ ldr(r3, MemOperand(sp, 2 * kPointerSize));
4058 const int kCalleeOffset = JSObject::kHeaderSize +
4059 Heap::kArgumentsCalleeIndex * kPointerSize;
4060 __ str(r3, FieldMemOperand(r0, kCalleeOffset));
4061
4062 // Use the length (smi tagged) and set that as an in-object property too.
4063 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
4064 const int kLengthOffset = JSObject::kHeaderSize +
4065 Heap::kArgumentsLengthIndex * kPointerSize;
4066 __ str(r2, FieldMemOperand(r0, kLengthOffset));
4067
4068 // Setup the elements pointer in the allocated arguments object.
4069 // If we allocated a parameter map, r4 will point there, otherwise
4070 // it will point to the backing store.
4071 __ add(r4, r0, Operand(Heap::kArgumentsObjectSize));
4072 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
4073
4074 // r0 = address of new object (tagged)
4075 // r1 = mapped parameter count (tagged)
4076 // r2 = argument count (tagged)
4077 // r4 = address of parameter map or backing store (tagged)
4078 // Initialize parameter map. If there are no mapped arguments, we're done.
4079 Label skip_parameter_map;
4080 __ cmp(r1, Operand(Smi::FromInt(0)));
4081 // Move backing store address to r3, because it is
4082 // expected there when filling in the unmapped arguments.
4083 __ mov(r3, r4, LeaveCC, eq);
4084 __ b(eq, &skip_parameter_map);
4085
4086 __ LoadRoot(r6, Heap::kNonStrictArgumentsElementsMapRootIndex);
4087 __ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset));
4088 __ add(r6, r1, Operand(Smi::FromInt(2)));
4089 __ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset));
4090 __ str(r8, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize));
4091 __ add(r6, r4, Operand(r1, LSL, 1));
4092 __ add(r6, r6, Operand(kParameterMapHeaderSize));
4093 __ str(r6, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize));
4094
4095 // Copy the parameter slots and the holes in the arguments.
4096 // We need to fill in mapped_parameter_count slots. They index the context,
4097 // where parameters are stored in reverse order, at
4098 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
4099 // The mapped parameter thus need to get indices
4100 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
4101 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
4102 // We loop from right to left.
4103 Label parameters_loop, parameters_test;
4104 __ mov(r6, r1);
4105 __ ldr(r9, MemOperand(sp, 0 * kPointerSize));
4106 __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
4107 __ sub(r9, r9, Operand(r1));
4108 __ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
4109 __ add(r3, r4, Operand(r6, LSL, 1));
4110 __ add(r3, r3, Operand(kParameterMapHeaderSize));
4111
4112 // r6 = loop variable (tagged)
4113 // r1 = mapping index (tagged)
4114 // r3 = address of backing store (tagged)
4115 // r4 = address of parameter map (tagged)
4116 // r5 = temporary scratch (a.o., for address calculation)
4117 // r7 = the hole value
4118 __ jmp(&parameters_test);
4119
4120 __ bind(&parameters_loop);
4121 __ sub(r6, r6, Operand(Smi::FromInt(1)));
4122 __ mov(r5, Operand(r6, LSL, 1));
4123 __ add(r5, r5, Operand(kParameterMapHeaderSize - kHeapObjectTag));
4124 __ str(r9, MemOperand(r4, r5));
4125 __ sub(r5, r5, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
4126 __ str(r7, MemOperand(r3, r5));
4127 __ add(r9, r9, Operand(Smi::FromInt(1)));
4128 __ bind(&parameters_test);
4129 __ cmp(r6, Operand(Smi::FromInt(0)));
4130 __ b(ne, &parameters_loop);
4131
4132 __ bind(&skip_parameter_map);
4133 // r2 = argument count (tagged)
4134 // r3 = address of backing store (tagged)
4135 // r5 = scratch
4136 // Copy arguments header and remaining slots (if there are any).
4137 __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex);
4138 __ str(r5, FieldMemOperand(r3, FixedArray::kMapOffset));
4139 __ str(r2, FieldMemOperand(r3, FixedArray::kLengthOffset));
4140
4141 Label arguments_loop, arguments_test;
4142 __ mov(r9, r1);
4143 __ ldr(r4, MemOperand(sp, 1 * kPointerSize));
4144 __ sub(r4, r4, Operand(r9, LSL, 1));
4145 __ jmp(&arguments_test);
4146
4147 __ bind(&arguments_loop);
4148 __ sub(r4, r4, Operand(kPointerSize));
4149 __ ldr(r6, MemOperand(r4, 0));
4150 __ add(r5, r3, Operand(r9, LSL, 1));
4151 __ str(r6, FieldMemOperand(r5, FixedArray::kHeaderSize));
4152 __ add(r9, r9, Operand(Smi::FromInt(1)));
4153
4154 __ bind(&arguments_test);
4155 __ cmp(r9, Operand(r2));
4156 __ b(lt, &arguments_loop);
4157
4158 // Return and remove the on-stack parameters.
4159 __ add(sp, sp, Operand(3 * kPointerSize));
4160 __ Ret();
4161
4162 // Do the runtime call to allocate the arguments object.
4163 // r2 = argument count (taggged)
4164 __ bind(&runtime);
4165 __ str(r2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count.
4166 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
4167 }
4168
4169
4170 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
4171 // sp[0] : number of parameters
4172 // sp[4] : receiver displacement
4173 // sp[8] : function
4174 // Check if the calling frame is an arguments adaptor frame.
3980 Label adaptor_frame, try_allocate, runtime; 4175 Label adaptor_frame, try_allocate, runtime;
3981 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 4176 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3982 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 4177 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
3983 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 4178 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3984 __ b(eq, &adaptor_frame); 4179 __ b(eq, &adaptor_frame);
3985 4180
3986 // Get the length from the frame. 4181 // Get the length from the frame.
3987 __ ldr(r1, MemOperand(sp, 0)); 4182 __ ldr(r1, MemOperand(sp, 0));
3988 __ b(&try_allocate); 4183 __ b(&try_allocate);
3989 4184
3990 // Patch the arguments.length and the parameters pointer. 4185 // Patch the arguments.length and the parameters pointer.
3991 __ bind(&adaptor_frame); 4186 __ bind(&adaptor_frame);
3992 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4187 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
3993 __ str(r1, MemOperand(sp, 0)); 4188 __ str(r1, MemOperand(sp, 0));
3994 __ add(r3, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); 4189 __ add(r3, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
3995 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); 4190 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
3996 __ str(r3, MemOperand(sp, 1 * kPointerSize)); 4191 __ str(r3, MemOperand(sp, 1 * kPointerSize));
3997 4192
3998 // Try the new space allocation. Start out with computing the size 4193 // Try the new space allocation. Start out with computing the size
3999 // of the arguments object and the elements array in words. 4194 // of the arguments object and the elements array in words.
4000 Label add_arguments_object; 4195 Label add_arguments_object;
4001 __ bind(&try_allocate); 4196 __ bind(&try_allocate);
4002 __ cmp(r1, Operand(0, RelocInfo::NONE)); 4197 __ cmp(r1, Operand(0, RelocInfo::NONE));
4003 __ b(eq, &add_arguments_object); 4198 __ b(eq, &add_arguments_object);
4004 __ mov(r1, Operand(r1, LSR, kSmiTagSize)); 4199 __ mov(r1, Operand(r1, LSR, kSmiTagSize));
4005 __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize)); 4200 __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize));
4006 __ bind(&add_arguments_object); 4201 __ bind(&add_arguments_object);
4007 __ add(r1, r1, Operand(GetArgumentsObjectSize() / kPointerSize)); 4202 __ add(r1, r1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize));
4008 4203
4009 // Do the allocation of both objects in one go. 4204 // Do the allocation of both objects in one go.
4010 __ AllocateInNewSpace( 4205 __ AllocateInNewSpace(r1,
4011 r1, 4206 r0,
4012 r0, 4207 r2,
4013 r2, 4208 r3,
4014 r3, 4209 &runtime,
4015 &runtime, 4210 static_cast<AllocationFlags>(TAG_OBJECT |
4016 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 4211 SIZE_IN_WORDS));
4017 4212
4018 // Get the arguments boilerplate from the current (global) context. 4213 // Get the arguments boilerplate from the current (global) context.
4019 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 4214 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
4020 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset)); 4215 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset));
4021 __ ldr(r4, MemOperand(r4, 4216 __ ldr(r4, MemOperand(r4, Context::SlotOffset(
4022 Context::SlotOffset(GetArgumentsBoilerplateIndex()))); 4217 Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX)));
4023 4218
4024 // Copy the JS object part. 4219 // Copy the JS object part.
4025 __ CopyFields(r0, r4, r3.bit(), JSObject::kHeaderSize / kPointerSize); 4220 __ CopyFields(r0, r4, r3.bit(), JSObject::kHeaderSize / kPointerSize);
4026 4221
4027 if (type_ == NEW_NON_STRICT) {
4028 // Setup the callee in-object property.
4029 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
4030 __ ldr(r3, MemOperand(sp, 2 * kPointerSize));
4031 const int kCalleeOffset = JSObject::kHeaderSize +
4032 Heap::kArgumentsCalleeIndex * kPointerSize;
4033 __ str(r3, FieldMemOperand(r0, kCalleeOffset));
4034 }
4035
4036 // Get the length (smi tagged) and set that as an in-object property too. 4222 // Get the length (smi tagged) and set that as an in-object property too.
4037 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 4223 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
4038 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); 4224 __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
4039 __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + 4225 __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize +
4040 Heap::kArgumentsLengthIndex * kPointerSize)); 4226 Heap::kArgumentsLengthIndex * kPointerSize));
4041 4227
4042 // If there are no actual arguments, we're done. 4228 // If there are no actual arguments, we're done.
4043 Label done; 4229 Label done;
4044 __ cmp(r1, Operand(0, RelocInfo::NONE)); 4230 __ cmp(r1, Operand(0, RelocInfo::NONE));
4045 __ b(eq, &done); 4231 __ b(eq, &done);
4046 4232
4047 // Get the parameters pointer from the stack. 4233 // Get the parameters pointer from the stack.
4048 __ ldr(r2, MemOperand(sp, 1 * kPointerSize)); 4234 __ ldr(r2, MemOperand(sp, 1 * kPointerSize));
4049 4235
4050 // Setup the elements pointer in the allocated arguments object and 4236 // Setup the elements pointer in the allocated arguments object and
4051 // initialize the header in the elements fixed array. 4237 // initialize the header in the elements fixed array.
4052 __ add(r4, r0, Operand(GetArgumentsObjectSize())); 4238 __ add(r4, r0, Operand(Heap::kArgumentsObjectSizeStrict));
4053 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 4239 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
4054 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex); 4240 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
4055 __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset)); 4241 __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset));
4056 __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset)); 4242 __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset));
4057 __ mov(r1, Operand(r1, LSR, kSmiTagSize)); // Untag the length for the loop. 4243 // Untag the length for the loop.
4244 __ mov(r1, Operand(r1, LSR, kSmiTagSize));
4058 4245
4059 // Copy the fixed array slots. 4246 // Copy the fixed array slots.
4060 Label loop; 4247 Label loop;
4061 // Setup r4 to point to the first array slot. 4248 // Setup r4 to point to the first array slot.
4062 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4249 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4063 __ bind(&loop); 4250 __ bind(&loop);
4064 // Pre-decrement r2 with kPointerSize on each iteration. 4251 // Pre-decrement r2 with kPointerSize on each iteration.
4065 // Pre-decrement in order to skip receiver. 4252 // Pre-decrement in order to skip receiver.
4066 __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex)); 4253 __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex));
4067 // Post-increment r4 with kPointerSize on each iteration. 4254 // Post-increment r4 with kPointerSize on each iteration.
4068 __ str(r3, MemOperand(r4, kPointerSize, PostIndex)); 4255 __ str(r3, MemOperand(r4, kPointerSize, PostIndex));
4069 __ sub(r1, r1, Operand(1)); 4256 __ sub(r1, r1, Operand(1));
4070 __ cmp(r1, Operand(0, RelocInfo::NONE)); 4257 __ cmp(r1, Operand(0, RelocInfo::NONE));
4071 __ b(ne, &loop); 4258 __ b(ne, &loop);
4072 4259
4073 // Return and remove the on-stack parameters. 4260 // Return and remove the on-stack parameters.
4074 __ bind(&done); 4261 __ bind(&done);
4075 __ add(sp, sp, Operand(3 * kPointerSize)); 4262 __ add(sp, sp, Operand(3 * kPointerSize));
4076 __ Ret(); 4263 __ Ret();
4077 4264
4078 // Do the runtime call to allocate the arguments object. 4265 // Do the runtime call to allocate the arguments object.
4079 __ bind(&runtime); 4266 __ bind(&runtime);
4080 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 4267 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
4081 } 4268 }
4082 4269
4083 4270
4084 void RegExpExecStub::Generate(MacroAssembler* masm) { 4271 void RegExpExecStub::Generate(MacroAssembler* masm) {
4085 // Just jump directly to runtime if native RegExp is not selected at compile 4272 // Just jump directly to runtime if native RegExp is not selected at compile
4086 // time or if regexp entry in generated code is turned off runtime switch or 4273 // time or if regexp entry in generated code is turned off runtime switch or
4087 // at compilation. 4274 // at compilation.
4088 #ifdef V8_INTERPRETED_REGEXP 4275 #ifdef V8_INTERPRETED_REGEXP
4089 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 4276 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
4090 #else // V8_INTERPRETED_REGEXP 4277 #else // V8_INTERPRETED_REGEXP
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4122 ExternalReference address_of_regexp_stack_memory_size = 4309 ExternalReference address_of_regexp_stack_memory_size =
4123 ExternalReference::address_of_regexp_stack_memory_size(isolate); 4310 ExternalReference::address_of_regexp_stack_memory_size(isolate);
4124 __ mov(r0, Operand(address_of_regexp_stack_memory_size)); 4311 __ mov(r0, Operand(address_of_regexp_stack_memory_size));
4125 __ ldr(r0, MemOperand(r0, 0)); 4312 __ ldr(r0, MemOperand(r0, 0));
4126 __ tst(r0, Operand(r0)); 4313 __ tst(r0, Operand(r0));
4127 __ b(eq, &runtime); 4314 __ b(eq, &runtime);
4128 4315
4129 // Check that the first argument is a JSRegExp object. 4316 // Check that the first argument is a JSRegExp object.
4130 __ ldr(r0, MemOperand(sp, kJSRegExpOffset)); 4317 __ ldr(r0, MemOperand(sp, kJSRegExpOffset));
4131 STATIC_ASSERT(kSmiTag == 0); 4318 STATIC_ASSERT(kSmiTag == 0);
4132 __ tst(r0, Operand(kSmiTagMask)); 4319 __ JumpIfSmi(r0, &runtime);
4133 __ b(eq, &runtime);
4134 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 4320 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
4135 __ b(ne, &runtime); 4321 __ b(ne, &runtime);
4136 4322
4137 // Check that the RegExp has been compiled (data contains a fixed array). 4323 // Check that the RegExp has been compiled (data contains a fixed array).
4138 __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset)); 4324 __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset));
4139 if (FLAG_debug_code) { 4325 if (FLAG_debug_code) {
4140 __ tst(regexp_data, Operand(kSmiTagMask)); 4326 __ tst(regexp_data, Operand(kSmiTagMask));
4141 __ Check(ne, "Unexpected type for RegExp data, FixedArray expected"); 4327 __ Check(ne, "Unexpected type for RegExp data, FixedArray expected");
4142 __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE); 4328 __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE);
4143 __ Check(eq, "Unexpected type for RegExp data, FixedArray expected"); 4329 __ Check(eq, "Unexpected type for RegExp data, FixedArray expected");
(...skipping 15 matching lines...) Expand all
4159 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 4345 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4160 __ add(r2, r2, Operand(2)); // r2 was a smi. 4346 __ add(r2, r2, Operand(2)); // r2 was a smi.
4161 // Check that the static offsets vector buffer is large enough. 4347 // Check that the static offsets vector buffer is large enough.
4162 __ cmp(r2, Operand(OffsetsVector::kStaticOffsetsVectorSize)); 4348 __ cmp(r2, Operand(OffsetsVector::kStaticOffsetsVectorSize));
4163 __ b(hi, &runtime); 4349 __ b(hi, &runtime);
4164 4350
4165 // r2: Number of capture registers 4351 // r2: Number of capture registers
4166 // regexp_data: RegExp data (FixedArray) 4352 // regexp_data: RegExp data (FixedArray)
4167 // Check that the second argument is a string. 4353 // Check that the second argument is a string.
4168 __ ldr(subject, MemOperand(sp, kSubjectOffset)); 4354 __ ldr(subject, MemOperand(sp, kSubjectOffset));
4169 __ tst(subject, Operand(kSmiTagMask)); 4355 __ JumpIfSmi(subject, &runtime);
4170 __ b(eq, &runtime);
4171 Condition is_string = masm->IsObjectStringType(subject, r0); 4356 Condition is_string = masm->IsObjectStringType(subject, r0);
4172 __ b(NegateCondition(is_string), &runtime); 4357 __ b(NegateCondition(is_string), &runtime);
4173 // Get the length of the string to r3. 4358 // Get the length of the string to r3.
4174 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset)); 4359 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset));
4175 4360
4176 // r2: Number of capture registers 4361 // r2: Number of capture registers
4177 // r3: Length of subject string as a smi 4362 // r3: Length of subject string as a smi
4178 // subject: Subject string 4363 // subject: Subject string
4179 // regexp_data: RegExp data (FixedArray) 4364 // regexp_data: RegExp data (FixedArray)
4180 // Check that the third argument is a positive smi less than the subject 4365 // Check that the third argument is a positive smi less than the subject
4181 // string length. A negative value will be greater (unsigned comparison). 4366 // string length. A negative value will be greater (unsigned comparison).
4182 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset)); 4367 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset));
4183 __ tst(r0, Operand(kSmiTagMask)); 4368 __ JumpIfNotSmi(r0, &runtime);
4184 __ b(ne, &runtime);
4185 __ cmp(r3, Operand(r0)); 4369 __ cmp(r3, Operand(r0));
4186 __ b(ls, &runtime); 4370 __ b(ls, &runtime);
4187 4371
4188 // r2: Number of capture registers 4372 // r2: Number of capture registers
4189 // subject: Subject string 4373 // subject: Subject string
4190 // regexp_data: RegExp data (FixedArray) 4374 // regexp_data: RegExp data (FixedArray)
4191 // Check that the fourth object is a JSArray object. 4375 // Check that the fourth object is a JSArray object.
4192 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); 4376 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
4193 __ tst(r0, Operand(kSmiTagMask)); 4377 __ JumpIfSmi(r0, &runtime);
4194 __ b(eq, &runtime);
4195 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 4378 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
4196 __ b(ne, &runtime); 4379 __ b(ne, &runtime);
4197 // Check that the JSArray is in fast case. 4380 // Check that the JSArray is in fast case.
4198 __ ldr(last_match_info_elements, 4381 __ ldr(last_match_info_elements,
4199 FieldMemOperand(r0, JSArray::kElementsOffset)); 4382 FieldMemOperand(r0, JSArray::kElementsOffset));
4200 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 4383 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
4201 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 4384 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
4202 __ cmp(r0, ip); 4385 __ cmp(r0, ip);
4203 __ b(ne, &runtime); 4386 __ b(ne, &runtime);
4204 // Check that the last match info has space for the capture registers and the 4387 // Check that the last match info has space for the capture registers and the
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
4250 STATIC_ASSERT(4 == kAsciiStringTag); 4433 STATIC_ASSERT(4 == kAsciiStringTag);
4251 STATIC_ASSERT(kTwoByteStringTag == 0); 4434 STATIC_ASSERT(kTwoByteStringTag == 0);
4252 // Find the code object based on the assumptions above. 4435 // Find the code object based on the assumptions above.
4253 __ and_(r0, r0, Operand(kStringEncodingMask)); 4436 __ and_(r0, r0, Operand(kStringEncodingMask));
4254 __ mov(r3, Operand(r0, ASR, 2), SetCC); 4437 __ mov(r3, Operand(r0, ASR, 2), SetCC);
4255 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); 4438 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
4256 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); 4439 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
4257 4440
4258 // Check that the irregexp code has been generated for the actual string 4441 // Check that the irregexp code has been generated for the actual string
4259 // encoding. If it has, the field contains a code object otherwise it contains 4442 // encoding. If it has, the field contains a code object otherwise it contains
4260 // the hole. 4443 // a smi (code flushing support).
4261 __ CompareObjectType(r7, r0, r0, CODE_TYPE); 4444 __ JumpIfSmi(r7, &runtime);
4262 __ b(ne, &runtime);
4263 4445
4264 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); 4446 // r3: encoding of subject string (1 if ASCII, 0 if two_byte);
4265 // r7: code 4447 // r7: code
4266 // subject: Subject string 4448 // subject: Subject string
4267 // regexp_data: RegExp data (FixedArray) 4449 // regexp_data: RegExp data (FixedArray)
4268 // Load used arguments before starting to push arguments for call to native 4450 // Load used arguments before starting to push arguments for call to native
4269 // RegExp code to avoid handling changing stack height. 4451 // RegExp code to avoid handling changing stack height.
4270 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); 4452 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset));
4271 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); 4453 __ mov(r1, Operand(r1, ASR, kSmiTagSize));
4272 4454
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
4453 4635
4454 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { 4636 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
4455 const int kMaxInlineLength = 100; 4637 const int kMaxInlineLength = 100;
4456 Label slowcase; 4638 Label slowcase;
4457 Label done; 4639 Label done;
4458 Factory* factory = masm->isolate()->factory(); 4640 Factory* factory = masm->isolate()->factory();
4459 4641
4460 __ ldr(r1, MemOperand(sp, kPointerSize * 2)); 4642 __ ldr(r1, MemOperand(sp, kPointerSize * 2));
4461 STATIC_ASSERT(kSmiTag == 0); 4643 STATIC_ASSERT(kSmiTag == 0);
4462 STATIC_ASSERT(kSmiTagSize == 1); 4644 STATIC_ASSERT(kSmiTagSize == 1);
4463 __ tst(r1, Operand(kSmiTagMask)); 4645 __ JumpIfNotSmi(r1, &slowcase);
4464 __ b(ne, &slowcase);
4465 __ cmp(r1, Operand(Smi::FromInt(kMaxInlineLength))); 4646 __ cmp(r1, Operand(Smi::FromInt(kMaxInlineLength)));
4466 __ b(hi, &slowcase); 4647 __ b(hi, &slowcase);
4467 // Smi-tagging is equivalent to multiplying by 2. 4648 // Smi-tagging is equivalent to multiplying by 2.
4468 // Allocate RegExpResult followed by FixedArray with size in ebx. 4649 // Allocate RegExpResult followed by FixedArray with size in ebx.
4469 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] 4650 // JSArray: [Map][empty properties][Elements][Length-smi][index][input]
4470 // Elements: [Map][Length][..elements..] 4651 // Elements: [Map][Length][..elements..]
4471 // Size of JSArray with two in-object properties and the header of a 4652 // Size of JSArray with two in-object properties and the header of a
4472 // FixedArray. 4653 // FixedArray.
4473 int objects_size = 4654 int objects_size =
4474 (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize; 4655 (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
4575 __ b(ne, &slow); 4756 __ b(ne, &slow);
4576 4757
4577 // Fast-case: Invoke the function now. 4758 // Fast-case: Invoke the function now.
4578 // r1: pushed function 4759 // r1: pushed function
4579 ParameterCount actual(argc_); 4760 ParameterCount actual(argc_);
4580 4761
4581 if (ReceiverMightBeImplicit()) { 4762 if (ReceiverMightBeImplicit()) {
4582 Label call_as_function; 4763 Label call_as_function;
4583 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); 4764 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
4584 __ b(eq, &call_as_function); 4765 __ b(eq, &call_as_function);
4585 __ InvokeFunction(r1, actual, JUMP_FUNCTION); 4766 __ InvokeFunction(r1,
4767 actual,
4768 JUMP_FUNCTION,
4769 NullCallWrapper(),
4770 CALL_AS_METHOD);
4586 __ bind(&call_as_function); 4771 __ bind(&call_as_function);
4587 } 4772 }
4588 __ InvokeFunction(r1, 4773 __ InvokeFunction(r1,
4589 actual, 4774 actual,
4590 JUMP_FUNCTION, 4775 JUMP_FUNCTION,
4591 NullCallWrapper(), 4776 NullCallWrapper(),
4592 CALL_AS_FUNCTION); 4777 CALL_AS_FUNCTION);
4593 4778
4594 // Slow-case: Non-function called. 4779 // Slow-case: Non-function called.
4595 __ bind(&slow); 4780 __ bind(&slow);
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after
5331 __ b(lt, &runtime); 5516 __ b(lt, &runtime);
5332 5517
5333 // r2: length 5518 // r2: length
5334 // r3: from index (untaged smi) 5519 // r3: from index (untaged smi)
5335 // r6 (a.k.a. to): to (smi) 5520 // r6 (a.k.a. to): to (smi)
5336 // r7 (a.k.a. from): from offset (smi) 5521 // r7 (a.k.a. from): from offset (smi)
5337 5522
5338 // Make sure first argument is a sequential (or flat) string. 5523 // Make sure first argument is a sequential (or flat) string.
5339 __ ldr(r5, MemOperand(sp, kStringOffset)); 5524 __ ldr(r5, MemOperand(sp, kStringOffset));
5340 STATIC_ASSERT(kSmiTag == 0); 5525 STATIC_ASSERT(kSmiTag == 0);
5341 __ tst(r5, Operand(kSmiTagMask)); 5526 __ JumpIfSmi(r5, &runtime);
5342 __ b(eq, &runtime);
5343 Condition is_string = masm->IsObjectStringType(r5, r1); 5527 Condition is_string = masm->IsObjectStringType(r5, r1);
5344 __ b(NegateCondition(is_string), &runtime); 5528 __ b(NegateCondition(is_string), &runtime);
5345 5529
5346 // r1: instance type 5530 // r1: instance type
5347 // r2: length 5531 // r2: length
5348 // r3: from index (untagged smi) 5532 // r3: from index (untagged smi)
5349 // r5: string 5533 // r5: string
5350 // r6 (a.k.a. to): to (smi) 5534 // r6 (a.k.a. to): to (smi)
5351 // r7 (a.k.a. from): from offset (smi) 5535 // r7 (a.k.a. from): from offset (smi)
5352 Label seq_string; 5536 Label seq_string;
(...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after
5969 __ str(arg, MemOperand(sp, stack_offset)); 6153 __ str(arg, MemOperand(sp, stack_offset));
5970 6154
5971 __ bind(&done); 6155 __ bind(&done);
5972 } 6156 }
5973 6157
5974 6158
5975 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { 6159 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
5976 ASSERT(state_ == CompareIC::SMIS); 6160 ASSERT(state_ == CompareIC::SMIS);
5977 Label miss; 6161 Label miss;
5978 __ orr(r2, r1, r0); 6162 __ orr(r2, r1, r0);
5979 __ tst(r2, Operand(kSmiTagMask)); 6163 __ JumpIfNotSmi(r2, &miss);
5980 __ b(ne, &miss);
5981 6164
5982 if (GetCondition() == eq) { 6165 if (GetCondition() == eq) {
5983 // For equality we do not care about the sign of the result. 6166 // For equality we do not care about the sign of the result.
5984 __ sub(r0, r0, r1, SetCC); 6167 __ sub(r0, r0, r1, SetCC);
5985 } else { 6168 } else {
5986 // Untag before subtracting to avoid handling overflow. 6169 // Untag before subtracting to avoid handling overflow.
5987 __ SmiUntag(r1); 6170 __ SmiUntag(r1);
5988 __ sub(r0, r1, SmiUntagOperand(r0)); 6171 __ sub(r0, r1, SmiUntagOperand(r0));
5989 } 6172 }
5990 __ Ret(); 6173 __ Ret();
5991 6174
5992 __ bind(&miss); 6175 __ bind(&miss);
5993 GenerateMiss(masm); 6176 GenerateMiss(masm);
5994 } 6177 }
5995 6178
5996 6179
5997 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { 6180 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
5998 ASSERT(state_ == CompareIC::HEAP_NUMBERS); 6181 ASSERT(state_ == CompareIC::HEAP_NUMBERS);
5999 6182
6000 Label generic_stub; 6183 Label generic_stub;
6001 Label unordered; 6184 Label unordered;
6002 Label miss; 6185 Label miss;
6003 __ and_(r2, r1, Operand(r0)); 6186 __ and_(r2, r1, Operand(r0));
6004 __ tst(r2, Operand(kSmiTagMask)); 6187 __ JumpIfSmi(r2, &generic_stub);
6005 __ b(eq, &generic_stub);
6006 6188
6007 __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE); 6189 __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE);
6008 __ b(ne, &miss); 6190 __ b(ne, &miss);
6009 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); 6191 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE);
6010 __ b(ne, &miss); 6192 __ b(ne, &miss);
6011 6193
6012 // Inlining the double comparison and falling back to the general compare 6194 // Inlining the double comparison and falling back to the general compare
6013 // stub if NaN is involved or VFP3 is unsupported. 6195 // stub if NaN is involved or VFP3 is unsupported.
6014 if (CpuFeatures::IsSupported(VFP3)) { 6196 if (CpuFeatures::IsSupported(VFP3)) {
6015 CpuFeatures::Scope scope(VFP3); 6197 CpuFeatures::Scope scope(VFP3);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
6144 6326
6145 __ bind(&miss); 6327 __ bind(&miss);
6146 GenerateMiss(masm); 6328 GenerateMiss(masm);
6147 } 6329 }
6148 6330
6149 6331
6150 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 6332 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
6151 ASSERT(state_ == CompareIC::OBJECTS); 6333 ASSERT(state_ == CompareIC::OBJECTS);
6152 Label miss; 6334 Label miss;
6153 __ and_(r2, r1, Operand(r0)); 6335 __ and_(r2, r1, Operand(r0));
6154 __ tst(r2, Operand(kSmiTagMask)); 6336 __ JumpIfSmi(r2, &miss);
6155 __ b(eq, &miss);
6156 6337
6157 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); 6338 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE);
6158 __ b(ne, &miss); 6339 __ b(ne, &miss);
6159 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); 6340 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE);
6160 __ b(ne, &miss); 6341 __ b(ne, &miss);
6161 6342
6162 ASSERT(GetCondition() == eq); 6343 ASSERT(GetCondition() == eq);
6163 __ sub(r0, r0, Operand(r1)); 6344 __ sub(r0, r0, Operand(r1));
6164 __ Ret(); 6345 __ Ret();
6165 6346
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
6461 } 6642 }
6462 __ Ret(); 6643 __ Ret();
6463 } 6644 }
6464 6645
6465 6646
6466 #undef __ 6647 #undef __
6467 6648
6468 } } // namespace v8::internal 6649 } } // namespace v8::internal
6469 6650
6470 #endif // V8_TARGET_ARCH_ARM 6651 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/deoptimizer-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698