| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/debug.h" | 10 #include "src/debug.h" |
| (...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | 1064 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); |
| 1065 __ JumpIfSmi(r1, &non_function); | 1065 __ JumpIfSmi(r1, &non_function); |
| 1066 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1066 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 1067 __ b(ne, &slow); | 1067 __ b(ne, &slow); |
| 1068 | 1068 |
| 1069 // 3a. Patch the first argument if necessary when calling a function. | 1069 // 3a. Patch the first argument if necessary when calling a function. |
| 1070 // r0: actual number of arguments | 1070 // r0: actual number of arguments |
| 1071 // r1: function | 1071 // r1: function |
| 1072 Label shift_arguments; | 1072 Label shift_arguments; |
| 1073 __ mov(r4, Operand::Zero()); // indicate regular JS_FUNCTION | 1073 __ mov(r4, Operand::Zero()); // indicate regular JS_FUNCTION |
| 1074 { Label convert_to_object, use_global_receiver, patch_receiver; | 1074 { Label convert_to_object, use_global_proxy, patch_receiver; |
| 1075 // Change context eagerly in case we need the global receiver. | 1075 // Change context eagerly in case we need the global receiver. |
| 1076 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1076 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1077 | 1077 |
| 1078 // Do not transform the receiver for strict mode functions. | 1078 // Do not transform the receiver for strict mode functions. |
| 1079 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1079 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1080 __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); | 1080 __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); |
| 1081 __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + | 1081 __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + |
| 1082 kSmiTagSize))); | 1082 kSmiTagSize))); |
| 1083 __ b(ne, &shift_arguments); | 1083 __ b(ne, &shift_arguments); |
| 1084 | 1084 |
| 1085 // Do not transform the receiver for native (Compilerhints already in r3). | 1085 // Do not transform the receiver for native (Compilerhints already in r3). |
| 1086 __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | 1086 __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); |
| 1087 __ b(ne, &shift_arguments); | 1087 __ b(ne, &shift_arguments); |
| 1088 | 1088 |
| 1089 // Compute the receiver in sloppy mode. | 1089 // Compute the receiver in sloppy mode. |
| 1090 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); | 1090 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 1091 __ ldr(r2, MemOperand(r2, -kPointerSize)); | 1091 __ ldr(r2, MemOperand(r2, -kPointerSize)); |
| 1092 // r0: actual number of arguments | 1092 // r0: actual number of arguments |
| 1093 // r1: function | 1093 // r1: function |
| 1094 // r2: first argument | 1094 // r2: first argument |
| 1095 __ JumpIfSmi(r2, &convert_to_object); | 1095 __ JumpIfSmi(r2, &convert_to_object); |
| 1096 | 1096 |
| 1097 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | 1097 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
| 1098 __ cmp(r2, r3); | 1098 __ cmp(r2, r3); |
| 1099 __ b(eq, &use_global_receiver); | 1099 __ b(eq, &use_global_proxy); |
| 1100 __ LoadRoot(r3, Heap::kNullValueRootIndex); | 1100 __ LoadRoot(r3, Heap::kNullValueRootIndex); |
| 1101 __ cmp(r2, r3); | 1101 __ cmp(r2, r3); |
| 1102 __ b(eq, &use_global_receiver); | 1102 __ b(eq, &use_global_proxy); |
| 1103 | 1103 |
| 1104 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1104 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 1105 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); | 1105 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); |
| 1106 __ b(ge, &shift_arguments); | 1106 __ b(ge, &shift_arguments); |
| 1107 | 1107 |
| 1108 __ bind(&convert_to_object); | 1108 __ bind(&convert_to_object); |
| 1109 | 1109 |
| 1110 { | 1110 { |
| 1111 // Enter an internal frame in order to preserve argument count. | 1111 // Enter an internal frame in order to preserve argument count. |
| 1112 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 1112 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 1113 __ SmiTag(r0); | 1113 __ SmiTag(r0); |
| 1114 __ push(r0); | 1114 __ push(r0); |
| 1115 | 1115 |
| 1116 __ push(r2); | 1116 __ push(r2); |
| 1117 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1117 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 1118 __ mov(r2, r0); | 1118 __ mov(r2, r0); |
| 1119 | 1119 |
| 1120 __ pop(r0); | 1120 __ pop(r0); |
| 1121 __ SmiUntag(r0); | 1121 __ SmiUntag(r0); |
| 1122 | 1122 |
| 1123 // Exit the internal frame. | 1123 // Exit the internal frame. |
| 1124 } | 1124 } |
| 1125 | 1125 |
| 1126 // Restore the function to r1, and the flag to r4. | 1126 // Restore the function to r1, and the flag to r4. |
| 1127 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | 1127 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); |
| 1128 __ mov(r4, Operand::Zero()); | 1128 __ mov(r4, Operand::Zero()); |
| 1129 __ jmp(&patch_receiver); | 1129 __ jmp(&patch_receiver); |
| 1130 | 1130 |
| 1131 __ bind(&use_global_receiver); | 1131 __ bind(&use_global_proxy); |
| 1132 __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 1132 __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
| 1133 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); | 1133 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalProxyOffset)); |
| 1134 | 1134 |
| 1135 __ bind(&patch_receiver); | 1135 __ bind(&patch_receiver); |
| 1136 __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); | 1136 __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 1137 __ str(r2, MemOperand(r3, -kPointerSize)); | 1137 __ str(r2, MemOperand(r3, -kPointerSize)); |
| 1138 | 1138 |
| 1139 __ jmp(&shift_arguments); | 1139 __ jmp(&shift_arguments); |
| 1140 } | 1140 } |
| 1141 | 1141 |
| 1142 // 3b. Check for function proxy. | 1142 // 3b. Check for function proxy. |
| 1143 __ bind(&slow); | 1143 __ bind(&slow); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1277 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 1278 __ b(ne, &push_receiver); | 1278 __ b(ne, &push_receiver); |
| 1279 | 1279 |
| 1280 // Change context eagerly to get the right global object if necessary. | 1280 // Change context eagerly to get the right global object if necessary. |
| 1281 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1281 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1282 // Load the shared function info while the function is still in r1. | 1282 // Load the shared function info while the function is still in r1. |
| 1283 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1283 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1284 | 1284 |
| 1285 // Compute the receiver. | 1285 // Compute the receiver. |
| 1286 // Do not transform the receiver for strict mode functions. | 1286 // Do not transform the receiver for strict mode functions. |
| 1287 Label call_to_object, use_global_receiver; | 1287 Label call_to_object, use_global_proxy; |
| 1288 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); | 1288 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); |
| 1289 __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + | 1289 __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + |
| 1290 kSmiTagSize))); | 1290 kSmiTagSize))); |
| 1291 __ b(ne, &push_receiver); | 1291 __ b(ne, &push_receiver); |
| 1292 | 1292 |
| 1293 // Do not transform the receiver for strict mode functions. | 1293 // Do not transform the receiver for strict mode functions. |
| 1294 __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | 1294 __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); |
| 1295 __ b(ne, &push_receiver); | 1295 __ b(ne, &push_receiver); |
| 1296 | 1296 |
| 1297 // Compute the receiver in sloppy mode. | 1297 // Compute the receiver in sloppy mode. |
| 1298 __ JumpIfSmi(r0, &call_to_object); | 1298 __ JumpIfSmi(r0, &call_to_object); |
| 1299 __ LoadRoot(r1, Heap::kNullValueRootIndex); | 1299 __ LoadRoot(r1, Heap::kNullValueRootIndex); |
| 1300 __ cmp(r0, r1); | 1300 __ cmp(r0, r1); |
| 1301 __ b(eq, &use_global_receiver); | 1301 __ b(eq, &use_global_proxy); |
| 1302 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 1302 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 1303 __ cmp(r0, r1); | 1303 __ cmp(r0, r1); |
| 1304 __ b(eq, &use_global_receiver); | 1304 __ b(eq, &use_global_proxy); |
| 1305 | 1305 |
| 1306 // Check if the receiver is already a JavaScript object. | 1306 // Check if the receiver is already a JavaScript object. |
| 1307 // r0: receiver | 1307 // r0: receiver |
| 1308 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1308 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 1309 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); | 1309 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); |
| 1310 __ b(ge, &push_receiver); | 1310 __ b(ge, &push_receiver); |
| 1311 | 1311 |
| 1312 // Convert the receiver to a regular object. | 1312 // Convert the receiver to a regular object. |
| 1313 // r0: receiver | 1313 // r0: receiver |
| 1314 __ bind(&call_to_object); | 1314 __ bind(&call_to_object); |
| 1315 __ push(r0); | 1315 __ push(r0); |
| 1316 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1316 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 1317 __ b(&push_receiver); | 1317 __ b(&push_receiver); |
| 1318 | 1318 |
| 1319 __ bind(&use_global_receiver); | 1319 __ bind(&use_global_proxy); |
| 1320 __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 1320 __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
| 1321 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 1321 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalProxyOffset)); |
| 1322 | 1322 |
| 1323 // Push the receiver. | 1323 // Push the receiver. |
| 1324 // r0: receiver | 1324 // r0: receiver |
| 1325 __ bind(&push_receiver); | 1325 __ bind(&push_receiver); |
| 1326 __ push(r0); | 1326 __ push(r0); |
| 1327 | 1327 |
| 1328 // Copy all arguments from the array to the stack. | 1328 // Copy all arguments from the array to the stack. |
| 1329 Label entry, loop; | 1329 Label entry, loop; |
| 1330 __ ldr(r0, MemOperand(fp, kIndexOffset)); | 1330 __ ldr(r0, MemOperand(fp, kIndexOffset)); |
| 1331 __ b(&entry); | 1331 __ b(&entry); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1551 __ bkpt(0); | 1551 __ bkpt(0); |
| 1552 } | 1552 } |
| 1553 } | 1553 } |
| 1554 | 1554 |
| 1555 | 1555 |
| 1556 #undef __ | 1556 #undef __ |
| 1557 | 1557 |
| 1558 } } // namespace v8::internal | 1558 } } // namespace v8::internal |
| 1559 | 1559 |
| 1560 #endif // V8_TARGET_ARCH_ARM | 1560 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |