| OLD | NEW |
| 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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 ASSERT(!extra2.is(name)); | 182 ASSERT(!extra2.is(name)); |
| 183 ASSERT(!extra2.is(scratch)); | 183 ASSERT(!extra2.is(scratch)); |
| 184 ASSERT(!extra2.is(extra)); | 184 ASSERT(!extra2.is(extra)); |
| 185 | 185 |
| 186 // Check scratch, extra and extra2 registers are valid. | 186 // Check scratch, extra and extra2 registers are valid. |
| 187 ASSERT(!scratch.is(no_reg)); | 187 ASSERT(!scratch.is(no_reg)); |
| 188 ASSERT(!extra.is(no_reg)); | 188 ASSERT(!extra.is(no_reg)); |
| 189 ASSERT(!extra2.is(no_reg)); | 189 ASSERT(!extra2.is(no_reg)); |
| 190 | 190 |
| 191 // Check that the receiver isn't a smi. | 191 // Check that the receiver isn't a smi. |
| 192 __ tst(receiver, Operand(kSmiTagMask)); | 192 __ JumpIfSmi(receiver, &miss); |
| 193 __ b(eq, &miss); | |
| 194 | 193 |
| 195 // Get the map of the receiver and compute the hash. | 194 // Get the map of the receiver and compute the hash. |
| 196 __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); | 195 __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); |
| 197 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 196 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 198 __ add(scratch, scratch, Operand(ip)); | 197 __ add(scratch, scratch, Operand(ip)); |
| 199 __ eor(scratch, scratch, Operand(flags)); | 198 __ eor(scratch, scratch, Operand(flags)); |
| 200 __ and_(scratch, | 199 __ and_(scratch, |
| 201 scratch, | 200 scratch, |
| 202 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize)); | 201 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize)); |
| 203 | 202 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 __ ldr(dst, FieldMemOperand(dst, offset)); | 274 __ ldr(dst, FieldMemOperand(dst, offset)); |
| 276 } | 275 } |
| 277 } | 276 } |
| 278 | 277 |
| 279 | 278 |
| 280 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 279 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
| 281 Register receiver, | 280 Register receiver, |
| 282 Register scratch, | 281 Register scratch, |
| 283 Label* miss_label) { | 282 Label* miss_label) { |
| 284 // Check that the receiver isn't a smi. | 283 // Check that the receiver isn't a smi. |
| 285 __ tst(receiver, Operand(kSmiTagMask)); | 284 __ JumpIfSmi(receiver, miss_label); |
| 286 __ b(eq, miss_label); | |
| 287 | 285 |
| 288 // Check that the object is a JS array. | 286 // Check that the object is a JS array. |
| 289 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); | 287 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); |
| 290 __ b(ne, miss_label); | 288 __ b(ne, miss_label); |
| 291 | 289 |
| 292 // Load length directly from the JS array. | 290 // Load length directly from the JS array. |
| 293 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 291 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 294 __ Ret(); | 292 __ Ret(); |
| 295 } | 293 } |
| 296 | 294 |
| 297 | 295 |
| 298 // Generate code to check if an object is a string. If the object is a | 296 // Generate code to check if an object is a string. If the object is a |
| 299 // heap object, its map's instance type is left in the scratch1 register. | 297 // heap object, its map's instance type is left in the scratch1 register. |
| 300 // If this is not needed, scratch1 and scratch2 may be the same register. | 298 // If this is not needed, scratch1 and scratch2 may be the same register. |
| 301 static void GenerateStringCheck(MacroAssembler* masm, | 299 static void GenerateStringCheck(MacroAssembler* masm, |
| 302 Register receiver, | 300 Register receiver, |
| 303 Register scratch1, | 301 Register scratch1, |
| 304 Register scratch2, | 302 Register scratch2, |
| 305 Label* smi, | 303 Label* smi, |
| 306 Label* non_string_object) { | 304 Label* non_string_object) { |
| 307 // Check that the receiver isn't a smi. | 305 // Check that the receiver isn't a smi. |
| 308 __ tst(receiver, Operand(kSmiTagMask)); | 306 __ JumpIfSmi(receiver, smi); |
| 309 __ b(eq, smi); | |
| 310 | 307 |
| 311 // Check that the object is a string. | 308 // Check that the object is a string. |
| 312 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 309 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 313 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 310 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 314 __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); | 311 __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); |
| 315 // The cast is to resolve the overload for the argument of 0x0. | 312 // The cast is to resolve the overload for the argument of 0x0. |
| 316 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); | 313 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); |
| 317 __ b(ne, non_string_object); | 314 __ b(ne, non_string_object); |
| 318 } | 315 } |
| 319 | 316 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 int index, | 371 int index, |
| 375 Map* transition, | 372 Map* transition, |
| 376 Register receiver_reg, | 373 Register receiver_reg, |
| 377 Register name_reg, | 374 Register name_reg, |
| 378 Register scratch, | 375 Register scratch, |
| 379 Label* miss_label) { | 376 Label* miss_label) { |
| 380 // r0 : value | 377 // r0 : value |
| 381 Label exit; | 378 Label exit; |
| 382 | 379 |
| 383 // Check that the receiver isn't a smi. | 380 // Check that the receiver isn't a smi. |
| 384 __ tst(receiver_reg, Operand(kSmiTagMask)); | 381 __ JumpIfSmi(receiver_reg, miss_label); |
| 385 __ b(eq, miss_label); | |
| 386 | 382 |
| 387 // Check that the map of the receiver hasn't changed. | 383 // Check that the map of the receiver hasn't changed. |
| 388 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); | 384 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
| 389 __ cmp(scratch, Operand(Handle<Map>(object->map()))); | 385 __ cmp(scratch, Operand(Handle<Map>(object->map()))); |
| 390 __ b(ne, miss_label); | 386 __ b(ne, miss_label); |
| 391 | 387 |
| 392 // Perform global security token check if needed. | 388 // Perform global security token check if needed. |
| 393 if (object->IsJSGlobalProxy()) { | 389 if (object->IsJSGlobalProxy()) { |
| 394 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 390 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 395 } | 391 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 424 // face of a transition we can use the old map here because the size of the | 420 // face of a transition we can use the old map here because the size of the |
| 425 // object and the number of in-object properties is not going to change. | 421 // object and the number of in-object properties is not going to change. |
| 426 index -= object->map()->inobject_properties(); | 422 index -= object->map()->inobject_properties(); |
| 427 | 423 |
| 428 if (index < 0) { | 424 if (index < 0) { |
| 429 // Set the property straight into the object. | 425 // Set the property straight into the object. |
| 430 int offset = object->map()->instance_size() + (index * kPointerSize); | 426 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 431 __ str(r0, FieldMemOperand(receiver_reg, offset)); | 427 __ str(r0, FieldMemOperand(receiver_reg, offset)); |
| 432 | 428 |
| 433 // Skip updating write barrier if storing a smi. | 429 // Skip updating write barrier if storing a smi. |
| 434 __ tst(r0, Operand(kSmiTagMask)); | 430 __ JumpIfSmi(r0, &exit); |
| 435 __ b(eq, &exit); | |
| 436 | 431 |
| 437 // Update the write barrier for the array address. | 432 // Update the write barrier for the array address. |
| 438 // Pass the now unused name_reg as a scratch register. | 433 // Pass the now unused name_reg as a scratch register. |
| 439 __ RecordWrite(receiver_reg, Operand(offset), name_reg, scratch); | 434 __ RecordWrite(receiver_reg, Operand(offset), name_reg, scratch); |
| 440 } else { | 435 } else { |
| 441 // Write to the properties array. | 436 // Write to the properties array. |
| 442 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 437 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 443 // Get the properties array | 438 // Get the properties array |
| 444 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 439 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 445 __ str(r0, FieldMemOperand(scratch, offset)); | 440 __ str(r0, FieldMemOperand(scratch, offset)); |
| 446 | 441 |
| 447 // Skip updating write barrier if storing a smi. | 442 // Skip updating write barrier if storing a smi. |
| 448 __ tst(r0, Operand(kSmiTagMask)); | 443 __ JumpIfSmi(r0, &exit); |
| 449 __ b(eq, &exit); | |
| 450 | 444 |
| 451 // Update the write barrier for the array address. | 445 // Update the write barrier for the array address. |
| 452 // Ok to clobber receiver_reg and name_reg, since we return. | 446 // Ok to clobber receiver_reg and name_reg, since we return. |
| 453 __ RecordWrite(scratch, Operand(offset), name_reg, receiver_reg); | 447 __ RecordWrite(scratch, Operand(offset), name_reg, receiver_reg); |
| 454 } | 448 } |
| 455 | 449 |
| 456 // Return the value (register r0). | 450 // Return the value (register r0). |
| 457 __ bind(&exit); | 451 __ bind(&exit); |
| 458 __ Ret(); | 452 __ Ret(); |
| 459 } | 453 } |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 void StubCompiler::GenerateLoadField(JSObject* object, | 1152 void StubCompiler::GenerateLoadField(JSObject* object, |
| 1159 JSObject* holder, | 1153 JSObject* holder, |
| 1160 Register receiver, | 1154 Register receiver, |
| 1161 Register scratch1, | 1155 Register scratch1, |
| 1162 Register scratch2, | 1156 Register scratch2, |
| 1163 Register scratch3, | 1157 Register scratch3, |
| 1164 int index, | 1158 int index, |
| 1165 String* name, | 1159 String* name, |
| 1166 Label* miss) { | 1160 Label* miss) { |
| 1167 // Check that the receiver isn't a smi. | 1161 // Check that the receiver isn't a smi. |
| 1168 __ tst(receiver, Operand(kSmiTagMask)); | 1162 __ JumpIfSmi(receiver, miss); |
| 1169 __ b(eq, miss); | |
| 1170 | 1163 |
| 1171 // Check that the maps haven't changed. | 1164 // Check that the maps haven't changed. |
| 1172 Register reg = | 1165 Register reg = |
| 1173 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1166 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
| 1174 name, miss); | 1167 name, miss); |
| 1175 GenerateFastPropertyLoad(masm(), r0, reg, holder, index); | 1168 GenerateFastPropertyLoad(masm(), r0, reg, holder, index); |
| 1176 __ Ret(); | 1169 __ Ret(); |
| 1177 } | 1170 } |
| 1178 | 1171 |
| 1179 | 1172 |
| 1180 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1173 void StubCompiler::GenerateLoadConstant(JSObject* object, |
| 1181 JSObject* holder, | 1174 JSObject* holder, |
| 1182 Register receiver, | 1175 Register receiver, |
| 1183 Register scratch1, | 1176 Register scratch1, |
| 1184 Register scratch2, | 1177 Register scratch2, |
| 1185 Register scratch3, | 1178 Register scratch3, |
| 1186 Object* value, | 1179 Object* value, |
| 1187 String* name, | 1180 String* name, |
| 1188 Label* miss) { | 1181 Label* miss) { |
| 1189 // Check that the receiver isn't a smi. | 1182 // Check that the receiver isn't a smi. |
| 1190 __ tst(receiver, Operand(kSmiTagMask)); | 1183 __ JumpIfSmi(receiver, miss); |
| 1191 __ b(eq, miss); | |
| 1192 | 1184 |
| 1193 // Check that the maps haven't changed. | 1185 // Check that the maps haven't changed. |
| 1194 Register reg = | 1186 Register reg = |
| 1195 CheckPrototypes(object, receiver, holder, | 1187 CheckPrototypes(object, receiver, holder, |
| 1196 scratch1, scratch2, scratch3, name, miss); | 1188 scratch1, scratch2, scratch3, name, miss); |
| 1197 | 1189 |
| 1198 // Return the constant value. | 1190 // Return the constant value. |
| 1199 __ mov(r0, Operand(Handle<Object>(value))); | 1191 __ mov(r0, Operand(Handle<Object>(value))); |
| 1200 __ Ret(); | 1192 __ Ret(); |
| 1201 } | 1193 } |
| 1202 | 1194 |
| 1203 | 1195 |
| 1204 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1196 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1205 JSObject* holder, | 1197 JSObject* holder, |
| 1206 Register receiver, | 1198 Register receiver, |
| 1207 Register name_reg, | 1199 Register name_reg, |
| 1208 Register scratch1, | 1200 Register scratch1, |
| 1209 Register scratch2, | 1201 Register scratch2, |
| 1210 Register scratch3, | 1202 Register scratch3, |
| 1211 AccessorInfo* callback, | 1203 AccessorInfo* callback, |
| 1212 String* name, | 1204 String* name, |
| 1213 Label* miss) { | 1205 Label* miss) { |
| 1214 // Check that the receiver isn't a smi. | 1206 // Check that the receiver isn't a smi. |
| 1215 __ tst(receiver, Operand(kSmiTagMask)); | 1207 __ JumpIfSmi(receiver, miss); |
| 1216 __ b(eq, miss); | |
| 1217 | 1208 |
| 1218 // Check that the maps haven't changed. | 1209 // Check that the maps haven't changed. |
| 1219 Register reg = | 1210 Register reg = |
| 1220 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1211 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
| 1221 name, miss); | 1212 name, miss); |
| 1222 | 1213 |
| 1223 // Build AccessorInfo::args_ list on the stack and push property name below | 1214 // Build AccessorInfo::args_ list on the stack and push property name below |
| 1224 // the exit frame to make GC aware of them and store pointers to them. | 1215 // the exit frame to make GC aware of them and store pointers to them. |
| 1225 __ push(receiver); | 1216 __ push(receiver); |
| 1226 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ | 1217 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1419 // Get the number of arguments. | 1410 // Get the number of arguments. |
| 1420 const int argc = arguments().immediate(); | 1411 const int argc = arguments().immediate(); |
| 1421 | 1412 |
| 1422 // Get the receiver from the stack. | 1413 // Get the receiver from the stack. |
| 1423 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1414 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 1424 | 1415 |
| 1425 // If the object is the holder then we know that it's a global | 1416 // If the object is the holder then we know that it's a global |
| 1426 // object which can only happen for contextual calls. In this case, | 1417 // object which can only happen for contextual calls. In this case, |
| 1427 // the receiver cannot be a smi. | 1418 // the receiver cannot be a smi. |
| 1428 if (object != holder) { | 1419 if (object != holder) { |
| 1429 __ tst(r0, Operand(kSmiTagMask)); | 1420 __ JumpIfSmi(r0, miss); |
| 1430 __ b(eq, miss); | |
| 1431 } | 1421 } |
| 1432 | 1422 |
| 1433 // Check that the maps haven't changed. | 1423 // Check that the maps haven't changed. |
| 1434 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); | 1424 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); |
| 1435 } | 1425 } |
| 1436 | 1426 |
| 1437 | 1427 |
| 1438 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1428 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, |
| 1439 JSFunction* function, | 1429 JSFunction* function, |
| 1440 Label* miss) { | 1430 Label* miss) { |
| 1441 // Get the value from the cell. | 1431 // Get the value from the cell. |
| 1442 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 1432 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
| 1443 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 1433 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
| 1444 | 1434 |
| 1445 // Check that the cell contains the same function. | 1435 // Check that the cell contains the same function. |
| 1446 if (heap()->InNewSpace(function)) { | 1436 if (heap()->InNewSpace(function)) { |
| 1447 // We can't embed a pointer to a function in new space so we have | 1437 // We can't embed a pointer to a function in new space so we have |
| 1448 // to verify that the shared function info is unchanged. This has | 1438 // to verify that the shared function info is unchanged. This has |
| 1449 // the nice side effect that multiple closures based on the same | 1439 // the nice side effect that multiple closures based on the same |
| 1450 // function can all use this call IC. Before we load through the | 1440 // function can all use this call IC. Before we load through the |
| 1451 // function, we have to verify that it still is a function. | 1441 // function, we have to verify that it still is a function. |
| 1452 __ tst(r1, Operand(kSmiTagMask)); | 1442 __ JumpIfSmi(r1, miss); |
| 1453 __ b(eq, miss); | |
| 1454 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 1443 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| 1455 __ b(ne, miss); | 1444 __ b(ne, miss); |
| 1456 | 1445 |
| 1457 // Check the shared function info. Make sure it hasn't changed. | 1446 // Check the shared function info. Make sure it hasn't changed. |
| 1458 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); | 1447 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); |
| 1459 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1448 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1460 __ cmp(r4, r3); | 1449 __ cmp(r4, r3); |
| 1461 __ b(ne, miss); | 1450 __ b(ne, miss); |
| 1462 } else { | 1451 } else { |
| 1463 __ cmp(r1, Operand(Handle<JSFunction>(function))); | 1452 __ cmp(r1, Operand(Handle<JSFunction>(function))); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1488 // ----------------------------------- | 1477 // ----------------------------------- |
| 1489 Label miss; | 1478 Label miss; |
| 1490 | 1479 |
| 1491 GenerateNameCheck(name, &miss); | 1480 GenerateNameCheck(name, &miss); |
| 1492 | 1481 |
| 1493 const int argc = arguments().immediate(); | 1482 const int argc = arguments().immediate(); |
| 1494 | 1483 |
| 1495 // Get the receiver of the function from the stack into r0. | 1484 // Get the receiver of the function from the stack into r0. |
| 1496 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1485 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 1497 // Check that the receiver isn't a smi. | 1486 // Check that the receiver isn't a smi. |
| 1498 __ tst(r0, Operand(kSmiTagMask)); | 1487 __ JumpIfSmi(r0, &miss); |
| 1499 __ b(eq, &miss); | |
| 1500 | 1488 |
| 1501 // Do the right check and compute the holder register. | 1489 // Do the right check and compute the holder register. |
| 1502 Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); | 1490 Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); |
| 1503 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); | 1491 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); |
| 1504 | 1492 |
| 1505 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); | 1493 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); |
| 1506 | 1494 |
| 1507 // Handle call cache miss. | 1495 // Handle call cache miss. |
| 1508 __ bind(&miss); | 1496 __ bind(&miss); |
| 1509 MaybeObject* maybe_result = GenerateMissBranch(); | 1497 MaybeObject* maybe_result = GenerateMissBranch(); |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1960 // arguments, bail out to the regular call. | 1948 // arguments, bail out to the regular call. |
| 1961 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1949 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 1962 | 1950 |
| 1963 Label miss; | 1951 Label miss; |
| 1964 GenerateNameCheck(name, &miss); | 1952 GenerateNameCheck(name, &miss); |
| 1965 | 1953 |
| 1966 if (cell == NULL) { | 1954 if (cell == NULL) { |
| 1967 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 1955 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 1968 | 1956 |
| 1969 STATIC_ASSERT(kSmiTag == 0); | 1957 STATIC_ASSERT(kSmiTag == 0); |
| 1970 __ tst(r1, Operand(kSmiTagMask)); | 1958 __ JumpIfSmi(r1, &miss); |
| 1971 __ b(eq, &miss); | |
| 1972 | 1959 |
| 1973 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 1960 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
| 1974 &miss); | 1961 &miss); |
| 1975 } else { | 1962 } else { |
| 1976 ASSERT(cell->value() == function); | 1963 ASSERT(cell->value() == function); |
| 1977 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1964 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); |
| 1978 GenerateLoadFunctionFromCell(cell, function, &miss); | 1965 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1979 } | 1966 } |
| 1980 | 1967 |
| 1981 // Load the char code argument. | 1968 // Load the char code argument. |
| 1982 Register code = r1; | 1969 Register code = r1; |
| 1983 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); | 1970 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); |
| 1984 | 1971 |
| 1985 // Check the code is a smi. | 1972 // Check the code is a smi. |
| 1986 Label slow; | 1973 Label slow; |
| 1987 STATIC_ASSERT(kSmiTag == 0); | 1974 STATIC_ASSERT(kSmiTag == 0); |
| 1988 __ tst(code, Operand(kSmiTagMask)); | 1975 __ JumpIfNotSmi(code, &slow); |
| 1989 __ b(ne, &slow); | |
| 1990 | 1976 |
| 1991 // Convert the smi code to uint16. | 1977 // Convert the smi code to uint16. |
| 1992 __ and_(code, code, Operand(Smi::FromInt(0xffff))); | 1978 __ and_(code, code, Operand(Smi::FromInt(0xffff))); |
| 1993 | 1979 |
| 1994 StringCharFromCodeGenerator char_from_code_generator(code, r0); | 1980 StringCharFromCodeGenerator char_from_code_generator(code, r0); |
| 1995 char_from_code_generator.GenerateFast(masm()); | 1981 char_from_code_generator.GenerateFast(masm()); |
| 1996 __ Drop(argc + 1); | 1982 __ Drop(argc + 1); |
| 1997 __ Ret(); | 1983 __ Ret(); |
| 1998 | 1984 |
| 1999 StubRuntimeCallHelper call_helper; | 1985 StubRuntimeCallHelper call_helper; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2181 // arguments, bail out to the regular call. | 2167 // arguments, bail out to the regular call. |
| 2182 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2168 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 2183 | 2169 |
| 2184 Label miss; | 2170 Label miss; |
| 2185 GenerateNameCheck(name, &miss); | 2171 GenerateNameCheck(name, &miss); |
| 2186 | 2172 |
| 2187 if (cell == NULL) { | 2173 if (cell == NULL) { |
| 2188 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2174 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 2189 | 2175 |
| 2190 STATIC_ASSERT(kSmiTag == 0); | 2176 STATIC_ASSERT(kSmiTag == 0); |
| 2191 __ tst(r1, Operand(kSmiTagMask)); | 2177 __ JumpIfSmi(r1, &miss); |
| 2192 __ b(eq, &miss); | |
| 2193 | 2178 |
| 2194 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2179 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
| 2195 &miss); | 2180 &miss); |
| 2196 } else { | 2181 } else { |
| 2197 ASSERT(cell->value() == function); | 2182 ASSERT(cell->value() == function); |
| 2198 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 2183 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); |
| 2199 GenerateLoadFunctionFromCell(cell, function, &miss); | 2184 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2200 } | 2185 } |
| 2201 | 2186 |
| 2202 // Load the (only) argument into r0. | 2187 // Load the (only) argument into r0. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2285 | 2270 |
| 2286 Label miss, miss_before_stack_reserved; | 2271 Label miss, miss_before_stack_reserved; |
| 2287 | 2272 |
| 2288 GenerateNameCheck(name, &miss_before_stack_reserved); | 2273 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2289 | 2274 |
| 2290 // Get the receiver from the stack. | 2275 // Get the receiver from the stack. |
| 2291 const int argc = arguments().immediate(); | 2276 const int argc = arguments().immediate(); |
| 2292 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2277 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2293 | 2278 |
| 2294 // Check that the receiver isn't a smi. | 2279 // Check that the receiver isn't a smi. |
| 2295 __ tst(r1, Operand(kSmiTagMask)); | 2280 __ JumpIfSmi(r1, &miss_before_stack_reserved); |
| 2296 __ b(eq, &miss_before_stack_reserved); | |
| 2297 | 2281 |
| 2298 __ IncrementCounter(counters->call_const(), 1, r0, r3); | 2282 __ IncrementCounter(counters->call_const(), 1, r0, r3); |
| 2299 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); | 2283 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); |
| 2300 | 2284 |
| 2301 ReserveSpaceForFastApiCall(masm(), r0); | 2285 ReserveSpaceForFastApiCall(masm(), r0); |
| 2302 | 2286 |
| 2303 // Check that the maps haven't changed and find a Holder as a side effect. | 2287 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2304 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2288 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
| 2305 depth, &miss); | 2289 depth, &miss); |
| 2306 | 2290 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2340 Label miss; | 2324 Label miss; |
| 2341 | 2325 |
| 2342 GenerateNameCheck(name, &miss); | 2326 GenerateNameCheck(name, &miss); |
| 2343 | 2327 |
| 2344 // Get the receiver from the stack | 2328 // Get the receiver from the stack |
| 2345 const int argc = arguments().immediate(); | 2329 const int argc = arguments().immediate(); |
| 2346 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2330 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2347 | 2331 |
| 2348 // Check that the receiver isn't a smi. | 2332 // Check that the receiver isn't a smi. |
| 2349 if (check != NUMBER_CHECK) { | 2333 if (check != NUMBER_CHECK) { |
| 2350 __ tst(r1, Operand(kSmiTagMask)); | 2334 __ JumpIfSmi(r1, &miss); |
| 2351 __ b(eq, &miss); | |
| 2352 } | 2335 } |
| 2353 | 2336 |
| 2354 // Make sure that it's okay not to patch the on stack receiver | 2337 // Make sure that it's okay not to patch the on stack receiver |
| 2355 // unless we're doing a receiver map check. | 2338 // unless we're doing a receiver map check. |
| 2356 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2339 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2357 | 2340 |
| 2358 SharedFunctionInfo* function_info = function->shared(); | 2341 SharedFunctionInfo* function_info = function->shared(); |
| 2359 switch (check) { | 2342 switch (check) { |
| 2360 case RECEIVER_MAP_CHECK: | 2343 case RECEIVER_MAP_CHECK: |
| 2361 __ IncrementCounter(masm()->isolate()->counters()->call_const(), | 2344 __ IncrementCounter(masm()->isolate()->counters()->call_const(), |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2391 break; | 2374 break; |
| 2392 | 2375 |
| 2393 case NUMBER_CHECK: { | 2376 case NUMBER_CHECK: { |
| 2394 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2377 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2395 // Calling non-strict non-builtins with a value as the receiver | 2378 // Calling non-strict non-builtins with a value as the receiver |
| 2396 // requires boxing. | 2379 // requires boxing. |
| 2397 __ jmp(&miss); | 2380 __ jmp(&miss); |
| 2398 } else { | 2381 } else { |
| 2399 Label fast; | 2382 Label fast; |
| 2400 // Check that the object is a smi or a heap number. | 2383 // Check that the object is a smi or a heap number. |
| 2401 __ tst(r1, Operand(kSmiTagMask)); | 2384 __ JumpIfSmi(r1, &fast); |
| 2402 __ b(eq, &fast); | |
| 2403 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); | 2385 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); |
| 2404 __ b(ne, &miss); | 2386 __ b(ne, &miss); |
| 2405 __ bind(&fast); | 2387 __ bind(&fast); |
| 2406 // Check that the maps starting from the prototype haven't changed. | 2388 // Check that the maps starting from the prototype haven't changed. |
| 2407 GenerateDirectLoadGlobalFunctionPrototype( | 2389 GenerateDirectLoadGlobalFunctionPrototype( |
| 2408 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); | 2390 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); |
| 2409 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2391 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
| 2410 r1, r4, name, &miss); | 2392 r1, r4, name, &miss); |
| 2411 } | 2393 } |
| 2412 break; | 2394 break; |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2612 String* name) { | 2594 String* name) { |
| 2613 // ----------- S t a t e ------------- | 2595 // ----------- S t a t e ------------- |
| 2614 // -- r0 : value | 2596 // -- r0 : value |
| 2615 // -- r1 : receiver | 2597 // -- r1 : receiver |
| 2616 // -- r2 : name | 2598 // -- r2 : name |
| 2617 // -- lr : return address | 2599 // -- lr : return address |
| 2618 // ----------------------------------- | 2600 // ----------------------------------- |
| 2619 Label miss; | 2601 Label miss; |
| 2620 | 2602 |
| 2621 // Check that the object isn't a smi. | 2603 // Check that the object isn't a smi. |
| 2622 __ tst(r1, Operand(kSmiTagMask)); | 2604 __ JumpIfSmi(r1, &miss); |
| 2623 __ b(eq, &miss); | |
| 2624 | 2605 |
| 2625 // Check that the map of the object hasn't changed. | 2606 // Check that the map of the object hasn't changed. |
| 2626 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 2607 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 2627 __ cmp(r3, Operand(Handle<Map>(object->map()))); | 2608 __ cmp(r3, Operand(Handle<Map>(object->map()))); |
| 2628 __ b(ne, &miss); | 2609 __ b(ne, &miss); |
| 2629 | 2610 |
| 2630 // Perform global security token check if needed. | 2611 // Perform global security token check if needed. |
| 2631 if (object->IsJSGlobalProxy()) { | 2612 if (object->IsJSGlobalProxy()) { |
| 2632 __ CheckAccessGlobalProxy(r1, r3, &miss); | 2613 __ CheckAccessGlobalProxy(r1, r3, &miss); |
| 2633 } | 2614 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2660 String* name) { | 2641 String* name) { |
| 2661 // ----------- S t a t e ------------- | 2642 // ----------- S t a t e ------------- |
| 2662 // -- r0 : value | 2643 // -- r0 : value |
| 2663 // -- r1 : receiver | 2644 // -- r1 : receiver |
| 2664 // -- r2 : name | 2645 // -- r2 : name |
| 2665 // -- lr : return address | 2646 // -- lr : return address |
| 2666 // ----------------------------------- | 2647 // ----------------------------------- |
| 2667 Label miss; | 2648 Label miss; |
| 2668 | 2649 |
| 2669 // Check that the object isn't a smi. | 2650 // Check that the object isn't a smi. |
| 2670 __ tst(r1, Operand(kSmiTagMask)); | 2651 __ JumpIfSmi(r1, &miss); |
| 2671 __ b(eq, &miss); | |
| 2672 | 2652 |
| 2673 // Check that the map of the object hasn't changed. | 2653 // Check that the map of the object hasn't changed. |
| 2674 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 2654 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 2675 __ cmp(r3, Operand(Handle<Map>(receiver->map()))); | 2655 __ cmp(r3, Operand(Handle<Map>(receiver->map()))); |
| 2676 __ b(ne, &miss); | 2656 __ b(ne, &miss); |
| 2677 | 2657 |
| 2678 // Perform global security token check if needed. | 2658 // Perform global security token check if needed. |
| 2679 if (receiver->IsJSGlobalProxy()) { | 2659 if (receiver->IsJSGlobalProxy()) { |
| 2680 __ CheckAccessGlobalProxy(r1, r3, &miss); | 2660 __ CheckAccessGlobalProxy(r1, r3, &miss); |
| 2681 } | 2661 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2752 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2732 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
| 2753 JSObject* object, | 2733 JSObject* object, |
| 2754 JSObject* last) { | 2734 JSObject* last) { |
| 2755 // ----------- S t a t e ------------- | 2735 // ----------- S t a t e ------------- |
| 2756 // -- r0 : receiver | 2736 // -- r0 : receiver |
| 2757 // -- lr : return address | 2737 // -- lr : return address |
| 2758 // ----------------------------------- | 2738 // ----------------------------------- |
| 2759 Label miss; | 2739 Label miss; |
| 2760 | 2740 |
| 2761 // Check that receiver is not a smi. | 2741 // Check that receiver is not a smi. |
| 2762 __ tst(r0, Operand(kSmiTagMask)); | 2742 __ JumpIfSmi(r0, &miss); |
| 2763 __ b(eq, &miss); | |
| 2764 | 2743 |
| 2765 // Check the maps of the full prototype chain. | 2744 // Check the maps of the full prototype chain. |
| 2766 CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); | 2745 CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); |
| 2767 | 2746 |
| 2768 // If the last object in the prototype chain is a global object, | 2747 // If the last object in the prototype chain is a global object, |
| 2769 // check that the global property cell is empty. | 2748 // check that the global property cell is empty. |
| 2770 if (last->IsGlobalObject()) { | 2749 if (last->IsGlobalObject()) { |
| 2771 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 2750 MaybeObject* cell = GenerateCheckPropertyCell(masm(), |
| 2772 GlobalObject::cast(last), | 2751 GlobalObject::cast(last), |
| 2773 name, | 2752 name, |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2897 // -- r0 : receiver | 2876 // -- r0 : receiver |
| 2898 // -- r2 : name | 2877 // -- r2 : name |
| 2899 // -- lr : return address | 2878 // -- lr : return address |
| 2900 // ----------------------------------- | 2879 // ----------------------------------- |
| 2901 Label miss; | 2880 Label miss; |
| 2902 | 2881 |
| 2903 // If the object is the holder then we know that it's a global | 2882 // If the object is the holder then we know that it's a global |
| 2904 // object which can only happen for contextual calls. In this case, | 2883 // object which can only happen for contextual calls. In this case, |
| 2905 // the receiver cannot be a smi. | 2884 // the receiver cannot be a smi. |
| 2906 if (object != holder) { | 2885 if (object != holder) { |
| 2907 __ tst(r0, Operand(kSmiTagMask)); | 2886 __ JumpIfSmi(r0, &miss); |
| 2908 __ b(eq, &miss); | |
| 2909 } | 2887 } |
| 2910 | 2888 |
| 2911 // Check that the map of the global has not changed. | 2889 // Check that the map of the global has not changed. |
| 2912 CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); | 2890 CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); |
| 2913 | 2891 |
| 2914 // Get the value from the cell. | 2892 // Get the value from the cell. |
| 2915 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 2893 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
| 2916 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 2894 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
| 2917 | 2895 |
| 2918 // Check for deleted property if property can actually be deleted. | 2896 // Check for deleted property if property can actually be deleted. |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3282 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 3260 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 3283 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); | 3261 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); |
| 3284 __ cmp(r2, r7); | 3262 __ cmp(r2, r7); |
| 3285 __ b(ne, &generic_stub_call); | 3263 __ b(ne, &generic_stub_call); |
| 3286 #endif | 3264 #endif |
| 3287 | 3265 |
| 3288 // Load the initial map and verify that it is in fact a map. | 3266 // Load the initial map and verify that it is in fact a map. |
| 3289 // r1: constructor function | 3267 // r1: constructor function |
| 3290 // r7: undefined | 3268 // r7: undefined |
| 3291 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 3269 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 3292 __ tst(r2, Operand(kSmiTagMask)); | 3270 __ JumpIfSmi(r2, &generic_stub_call); |
| 3293 __ b(eq, &generic_stub_call); | |
| 3294 __ CompareObjectType(r2, r3, r4, MAP_TYPE); | 3271 __ CompareObjectType(r2, r3, r4, MAP_TYPE); |
| 3295 __ b(ne, &generic_stub_call); | 3272 __ b(ne, &generic_stub_call); |
| 3296 | 3273 |
| 3297 #ifdef DEBUG | 3274 #ifdef DEBUG |
| 3298 // Cannot construct functions this way. | 3275 // Cannot construct functions this way. |
| 3299 // r0: argc | 3276 // r0: argc |
| 3300 // r1: constructor function | 3277 // r1: constructor function |
| 3301 // r2: initial map | 3278 // r2: initial map |
| 3302 // r7: undefined | 3279 // r7: undefined |
| 3303 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); | 3280 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); |
| (...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4196 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4173 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 4197 __ Jump(ic, RelocInfo::CODE_TARGET); | 4174 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 4198 } | 4175 } |
| 4199 | 4176 |
| 4200 | 4177 |
| 4201 #undef __ | 4178 #undef __ |
| 4202 | 4179 |
| 4203 } } // namespace v8::internal | 4180 } } // namespace v8::internal |
| 4204 | 4181 |
| 4205 #endif // V8_TARGET_ARCH_ARM | 4182 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |