| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 Label* gc_required) { | 183 Label* gc_required) { |
| 184 Label not_empty, allocated; | 184 Label not_empty, allocated; |
| 185 | 185 |
| 186 // Load the initial map from the array function. | 186 // Load the initial map from the array function. |
| 187 __ ldr(elements_array_storage, | 187 __ ldr(elements_array_storage, |
| 188 FieldMemOperand(array_function, | 188 FieldMemOperand(array_function, |
| 189 JSFunction::kPrototypeOrInitialMapOffset)); | 189 JSFunction::kPrototypeOrInitialMapOffset)); |
| 190 | 190 |
| 191 // Check whether an empty sized array is requested. | 191 // Check whether an empty sized array is requested. |
| 192 __ tst(array_size, array_size); | 192 __ tst(array_size, array_size); |
| 193 __ b(nz, ¬_empty); | 193 __ b(ne, ¬_empty); |
| 194 | 194 |
| 195 // If an empty array is requested allocate a small elements array anyway. This | 195 // If an empty array is requested allocate a small elements array anyway. This |
| 196 // keeps the code below free of special casing for the empty array. | 196 // keeps the code below free of special casing for the empty array. |
| 197 int size = JSArray::kSize + | 197 int size = JSArray::kSize + |
| 198 FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); | 198 FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); |
| 199 __ AllocateInNewSpace(size, | 199 __ AllocateInNewSpace(size, |
| 200 result, | 200 result, |
| 201 elements_array_end, | 201 elements_array_end, |
| 202 scratch1, | 202 scratch1, |
| 203 gc_required, | 203 gc_required, |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 | 495 |
| 496 Register function = r1; | 496 Register function = r1; |
| 497 if (FLAG_debug_code) { | 497 if (FLAG_debug_code) { |
| 498 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2); | 498 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2); |
| 499 __ cmp(function, Operand(r2)); | 499 __ cmp(function, Operand(r2)); |
| 500 __ Assert(eq, "Unexpected String function"); | 500 __ Assert(eq, "Unexpected String function"); |
| 501 } | 501 } |
| 502 | 502 |
| 503 // Load the first arguments in r0 and get rid of the rest. | 503 // Load the first arguments in r0 and get rid of the rest. |
| 504 Label no_arguments; | 504 Label no_arguments; |
| 505 __ cmp(r0, Operand(0)); | 505 __ cmp(r0, Operand(0, RelocInfo::NONE)); |
| 506 __ b(eq, &no_arguments); | 506 __ b(eq, &no_arguments); |
| 507 // First args = sp[(argc - 1) * 4]. | 507 // First args = sp[(argc - 1) * 4]. |
| 508 __ sub(r0, r0, Operand(1)); | 508 __ sub(r0, r0, Operand(1)); |
| 509 __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex)); | 509 __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex)); |
| 510 // sp now point to args[0], drop args[0] + receiver. | 510 // sp now point to args[0], drop args[0] + receiver. |
| 511 __ Drop(2); | 511 __ Drop(2); |
| 512 | 512 |
| 513 Register argument = r2; | 513 Register argument = r2; |
| 514 Label not_cached, argument_is_string; | 514 Label not_cached, argument_is_string; |
| 515 NumberToStringStub::GenerateLookupNumberStringCache( | 515 NumberToStringStub::GenerateLookupNumberStringCache( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 539 TAG_OBJECT); | 539 TAG_OBJECT); |
| 540 | 540 |
| 541 // Initialising the String Object. | 541 // Initialising the String Object. |
| 542 Register map = r3; | 542 Register map = r3; |
| 543 __ LoadGlobalFunctionInitialMap(function, map, r4); | 543 __ LoadGlobalFunctionInitialMap(function, map, r4); |
| 544 if (FLAG_debug_code) { | 544 if (FLAG_debug_code) { |
| 545 __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset)); | 545 __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset)); |
| 546 __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2)); | 546 __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2)); |
| 547 __ Assert(eq, "Unexpected string wrapper instance size"); | 547 __ Assert(eq, "Unexpected string wrapper instance size"); |
| 548 __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); | 548 __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); |
| 549 __ cmp(r4, Operand(0)); | 549 __ cmp(r4, Operand(0, RelocInfo::NONE)); |
| 550 __ Assert(eq, "Unexpected unused properties of string wrapper"); | 550 __ Assert(eq, "Unexpected unused properties of string wrapper"); |
| 551 } | 551 } |
| 552 __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset)); | 552 __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 553 | 553 |
| 554 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); | 554 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); |
| 555 __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 555 __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
| 556 __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); | 556 __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 557 | 557 |
| 558 __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset)); | 558 __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset)); |
| 559 | 559 |
| 560 // Ensure the object is fully initialized. | 560 // Ensure the object is fully initialized. |
| 561 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); | 561 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
| 562 | 562 |
| 563 __ Ret(); | 563 __ Ret(); |
| 564 | 564 |
| 565 // The argument was not found in the number to string cache. Check | 565 // The argument was not found in the number to string cache. Check |
| 566 // if it's a string already before calling the conversion builtin. | 566 // if it's a string already before calling the conversion builtin. |
| 567 Label convert_argument; | 567 Label convert_argument; |
| 568 __ bind(¬_cached); | 568 __ bind(¬_cached); |
| 569 __ BranchOnSmi(r0, &convert_argument); | 569 __ JumpIfSmi(r0, &convert_argument); |
| 570 | 570 |
| 571 // Is it a String? | 571 // Is it a String? |
| 572 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 572 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 573 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 573 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
| 574 ASSERT(kNotStringTag != 0); | 574 ASSERT(kNotStringTag != 0); |
| 575 __ tst(r3, Operand(kIsNotStringMask)); | 575 __ tst(r3, Operand(kIsNotStringMask)); |
| 576 __ b(ne, &convert_argument); | 576 __ b(ne, &convert_argument); |
| 577 __ mov(argument, r0); | 577 __ mov(argument, r0); |
| 578 __ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4); | 578 __ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4); |
| 579 __ b(&argument_is_string); | 579 __ b(&argument_is_string); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 // preconditions is not met, the code bails out to the runtime call. | 659 // preconditions is not met, the code bails out to the runtime call. |
| 660 Label rt_call, allocated; | 660 Label rt_call, allocated; |
| 661 if (FLAG_inline_new) { | 661 if (FLAG_inline_new) { |
| 662 Label undo_allocation; | 662 Label undo_allocation; |
| 663 #ifdef ENABLE_DEBUGGER_SUPPORT | 663 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 664 ExternalReference debug_step_in_fp = | 664 ExternalReference debug_step_in_fp = |
| 665 ExternalReference::debug_step_in_fp_address(); | 665 ExternalReference::debug_step_in_fp_address(); |
| 666 __ mov(r2, Operand(debug_step_in_fp)); | 666 __ mov(r2, Operand(debug_step_in_fp)); |
| 667 __ ldr(r2, MemOperand(r2)); | 667 __ ldr(r2, MemOperand(r2)); |
| 668 __ tst(r2, r2); | 668 __ tst(r2, r2); |
| 669 __ b(nz, &rt_call); | 669 __ b(ne, &rt_call); |
| 670 #endif | 670 #endif |
| 671 | 671 |
| 672 // Load the initial map and verify that it is in fact a map. | 672 // Load the initial map and verify that it is in fact a map. |
| 673 // r1: constructor function | 673 // r1: constructor function |
| 674 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 674 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 675 __ tst(r2, Operand(kSmiTagMask)); | 675 __ tst(r2, Operand(kSmiTagMask)); |
| 676 __ b(eq, &rt_call); | 676 __ b(eq, &rt_call); |
| 677 __ CompareObjectType(r2, r3, r4, MAP_TYPE); | 677 __ CompareObjectType(r2, r3, r4, MAP_TYPE); |
| 678 __ b(ne, &rt_call); | 678 __ b(ne, &rt_call); |
| 679 | 679 |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); | 1149 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); |
| 1150 } | 1150 } |
| 1151 | 1151 |
| 1152 | 1152 |
| 1153 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { | 1153 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { |
| 1154 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); | 1154 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); |
| 1155 } | 1155 } |
| 1156 | 1156 |
| 1157 | 1157 |
| 1158 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { | 1158 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { |
| 1159 __ stop("builtins-arm.cc: NotifyOSR"); | 1159 // For now, we are relying on the fact that Runtime::NotifyOSR |
| 1160 // doesn't do any garbage collection which allows us to save/restore |
| 1161 // the registers without worrying about which of them contain |
| 1162 // pointers. This seems a bit fragile. |
| 1163 __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); |
| 1164 __ EnterInternalFrame(); |
| 1165 __ CallRuntime(Runtime::kNotifyOSR, 0); |
| 1166 __ LeaveInternalFrame(); |
| 1167 __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); |
| 1168 __ Ret(); |
| 1160 } | 1169 } |
| 1161 | 1170 |
| 1162 | 1171 |
| 1163 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { | 1172 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { |
| 1164 __ stop("builtins-arm.cc: OnStackReplacement"); | 1173 // Probe the CPU to set the supported features, because this builtin |
| 1174 // may be called before the initialization performs CPU setup. |
| 1175 CpuFeatures::Probe(false); |
| 1176 |
| 1177 // Lookup the function in the JavaScript frame and push it as an |
| 1178 // argument to the on-stack replacement function. |
| 1179 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1180 __ EnterInternalFrame(); |
| 1181 __ push(r0); |
| 1182 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); |
| 1183 __ LeaveInternalFrame(); |
| 1184 |
| 1185 // If the result was -1 it means that we couldn't optimize the |
| 1186 // function. Just return and continue in the unoptimized version. |
| 1187 Label skip; |
| 1188 __ cmp(r0, Operand(Smi::FromInt(-1))); |
| 1189 __ b(ne, &skip); |
| 1190 __ Ret(); |
| 1191 |
| 1192 __ bind(&skip); |
| 1193 // Untag the AST id and push it on the stack. |
| 1194 __ SmiUntag(r0); |
| 1195 __ push(r0); |
| 1196 |
| 1197 // Generate the code for doing the frame-to-frame translation using |
| 1198 // the deoptimizer infrastructure. |
| 1199 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
| 1200 generator.Generate(); |
| 1165 } | 1201 } |
| 1166 | 1202 |
| 1167 | 1203 |
| 1168 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { | 1204 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { |
| 1169 // 1. Make sure we have at least one argument. | 1205 // 1. Make sure we have at least one argument. |
| 1170 // r0: actual number of arguments | 1206 // r0: actual number of arguments |
| 1171 { Label done; | 1207 { Label done; |
| 1172 __ tst(r0, Operand(r0)); | 1208 __ tst(r0, Operand(r0)); |
| 1173 __ b(ne, &done); | 1209 __ b(ne, &done); |
| 1174 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 1210 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1188 __ b(ne, &non_function); | 1224 __ b(ne, &non_function); |
| 1189 | 1225 |
| 1190 // 3a. Patch the first argument if necessary when calling a function. | 1226 // 3a. Patch the first argument if necessary when calling a function. |
| 1191 // r0: actual number of arguments | 1227 // r0: actual number of arguments |
| 1192 // r1: function | 1228 // r1: function |
| 1193 Label shift_arguments; | 1229 Label shift_arguments; |
| 1194 { Label convert_to_object, use_global_receiver, patch_receiver; | 1230 { Label convert_to_object, use_global_receiver, patch_receiver; |
| 1195 // Change context eagerly in case we need the global receiver. | 1231 // Change context eagerly in case we need the global receiver. |
| 1196 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1232 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1197 | 1233 |
| 1234 // Do not transform the receiver for strict mode functions. |
| 1235 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1236 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); |
| 1237 __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + |
| 1238 kSmiTagSize))); |
| 1239 __ b(ne, &shift_arguments); |
| 1240 |
| 1241 // Compute the receiver in non-strict mode. |
| 1198 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); | 1242 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 1199 __ ldr(r2, MemOperand(r2, -kPointerSize)); | 1243 __ ldr(r2, MemOperand(r2, -kPointerSize)); |
| 1200 // r0: actual number of arguments | 1244 // r0: actual number of arguments |
| 1201 // r1: function | 1245 // r1: function |
| 1202 // r2: first argument | 1246 // r2: first argument |
| 1203 __ tst(r2, Operand(kSmiTagMask)); | 1247 __ tst(r2, Operand(kSmiTagMask)); |
| 1204 __ b(eq, &convert_to_object); | 1248 __ b(eq, &convert_to_object); |
| 1205 | 1249 |
| 1206 __ LoadRoot(r3, Heap::kNullValueRootIndex); | 1250 __ LoadRoot(r3, Heap::kNullValueRootIndex); |
| 1207 __ cmp(r2, r3); | 1251 __ cmp(r2, r3); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 | 1395 |
| 1352 // Push current limit and index. | 1396 // Push current limit and index. |
| 1353 __ bind(&okay); | 1397 __ bind(&okay); |
| 1354 __ push(r0); // limit | 1398 __ push(r0); // limit |
| 1355 __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index | 1399 __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index |
| 1356 __ push(r1); | 1400 __ push(r1); |
| 1357 | 1401 |
| 1358 // Change context eagerly to get the right global object if necessary. | 1402 // Change context eagerly to get the right global object if necessary. |
| 1359 __ ldr(r0, MemOperand(fp, kFunctionOffset)); | 1403 __ ldr(r0, MemOperand(fp, kFunctionOffset)); |
| 1360 __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); | 1404 __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); |
| 1405 // Load the shared function info while the function is still in r0. |
| 1406 __ ldr(r1, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); |
| 1361 | 1407 |
| 1362 // Compute the receiver. | 1408 // Compute the receiver. |
| 1363 Label call_to_object, use_global_receiver, push_receiver; | 1409 Label call_to_object, use_global_receiver, push_receiver; |
| 1364 __ ldr(r0, MemOperand(fp, kRecvOffset)); | 1410 __ ldr(r0, MemOperand(fp, kRecvOffset)); |
| 1411 |
| 1412 // Do not transform the receiver for strict mode functions. |
| 1413 __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCompilerHintsOffset)); |
| 1414 __ tst(r1, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + |
| 1415 kSmiTagSize))); |
| 1416 __ b(ne, &push_receiver); |
| 1417 |
| 1418 // Compute the receiver in non-strict mode. |
| 1365 __ tst(r0, Operand(kSmiTagMask)); | 1419 __ tst(r0, Operand(kSmiTagMask)); |
| 1366 __ b(eq, &call_to_object); | 1420 __ b(eq, &call_to_object); |
| 1367 __ LoadRoot(r1, Heap::kNullValueRootIndex); | 1421 __ LoadRoot(r1, Heap::kNullValueRootIndex); |
| 1368 __ cmp(r0, r1); | 1422 __ cmp(r0, r1); |
| 1369 __ b(eq, &use_global_receiver); | 1423 __ b(eq, &use_global_receiver); |
| 1370 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 1424 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 1371 __ cmp(r0, r1); | 1425 __ cmp(r0, r1); |
| 1372 __ b(eq, &use_global_receiver); | 1426 __ b(eq, &use_global_receiver); |
| 1373 | 1427 |
| 1374 // Check if the receiver is already a JavaScript object. | 1428 // Check if the receiver is already a JavaScript object. |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1565 __ bind(&dont_adapt_arguments); | 1619 __ bind(&dont_adapt_arguments); |
| 1566 __ Jump(r3); | 1620 __ Jump(r3); |
| 1567 } | 1621 } |
| 1568 | 1622 |
| 1569 | 1623 |
| 1570 #undef __ | 1624 #undef __ |
| 1571 | 1625 |
| 1572 } } // namespace v8::internal | 1626 } } // namespace v8::internal |
| 1573 | 1627 |
| 1574 #endif // V8_TARGET_ARCH_ARM | 1628 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |