OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name); | 426 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name); |
427 ASSERT(cell->value()->IsTheHole()); | 427 ASSERT(cell->value()->IsTheHole()); |
428 __ mov(scratch, Operand(cell)); | 428 __ mov(scratch, Operand(cell)); |
429 __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 429 __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
430 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 430 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
431 __ cmp(scratch, ip); | 431 __ cmp(scratch, ip); |
432 __ b(ne, miss); | 432 __ b(ne, miss); |
433 } | 433 } |
434 | 434 |
435 | 435 |
436 void BaseStoreStubCompiler::GenerateNegativeHolderLookup( | 436 void StoreStubCompiler::GenerateNegativeHolderLookup( |
437 MacroAssembler* masm, | 437 MacroAssembler* masm, |
438 Handle<JSObject> holder, | 438 Handle<JSObject> holder, |
439 Register holder_reg, | 439 Register holder_reg, |
440 Handle<Name> name, | 440 Handle<Name> name, |
441 Label* miss) { | 441 Label* miss) { |
442 if (holder->IsJSGlobalObject()) { | 442 if (holder->IsJSGlobalObject()) { |
443 GenerateCheckPropertyCell( | 443 GenerateCheckPropertyCell( |
444 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); | 444 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); |
445 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 445 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
446 GenerateDictionaryNegativeLookup( | 446 GenerateDictionaryNegativeLookup( |
447 masm, miss, holder_reg, name, scratch1(), scratch2()); | 447 masm, miss, holder_reg, name, scratch1(), scratch2()); |
448 } | 448 } |
449 } | 449 } |
450 | 450 |
451 | 451 |
452 // Generate StoreTransition code, value is passed in r0 register. | 452 // Generate StoreTransition code, value is passed in r0 register. |
453 // When leaving generated code after success, the receiver_reg and name_reg | 453 // When leaving generated code after success, the receiver_reg and name_reg |
454 // may be clobbered. Upon branch to miss_label, the receiver and name | 454 // may be clobbered. Upon branch to miss_label, the receiver and name |
455 // registers have their original values. | 455 // registers have their original values. |
456 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 456 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
457 Handle<JSObject> object, | 457 Handle<JSObject> object, |
458 LookupResult* lookup, | 458 LookupResult* lookup, |
459 Handle<Map> transition, | 459 Handle<Map> transition, |
460 Handle<Name> name, | 460 Handle<Name> name, |
461 Register receiver_reg, | 461 Register receiver_reg, |
462 Register storage_reg, | 462 Register storage_reg, |
463 Register value_reg, | 463 Register value_reg, |
464 Register scratch1, | 464 Register scratch1, |
465 Register scratch2, | 465 Register scratch2, |
466 Register scratch3, | 466 Register scratch3, |
467 Label* miss_label, | 467 Label* miss_label, |
468 Label* slow) { | 468 Label* slow) { |
469 // r0 : value | 469 // r0 : value |
470 Label exit; | 470 Label exit; |
471 | 471 |
472 int descriptor = transition->LastAdded(); | 472 int descriptor = transition->LastAdded(); |
473 DescriptorArray* descriptors = transition->instance_descriptors(); | 473 DescriptorArray* descriptors = transition->instance_descriptors(); |
474 PropertyDetails details = descriptors->GetDetails(descriptor); | 474 PropertyDetails details = descriptors->GetDetails(descriptor); |
475 Representation representation = details.representation(); | 475 Representation representation = details.representation(); |
476 ASSERT(!representation.IsNone()); | 476 ASSERT(!representation.IsNone()); |
477 | 477 |
478 if (details.type() == CONSTANT) { | 478 if (details.type() == CONSTANT) { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 ASSERT(value_reg.is(r0)); | 610 ASSERT(value_reg.is(r0)); |
611 __ bind(&exit); | 611 __ bind(&exit); |
612 __ Ret(); | 612 __ Ret(); |
613 } | 613 } |
614 | 614 |
615 | 615 |
616 // Generate StoreField code, value is passed in r0 register. | 616 // Generate StoreField code, value is passed in r0 register. |
617 // When leaving generated code after success, the receiver_reg and name_reg | 617 // When leaving generated code after success, the receiver_reg and name_reg |
618 // may be clobbered. Upon branch to miss_label, the receiver and name | 618 // may be clobbered. Upon branch to miss_label, the receiver and name |
619 // registers have their original values. | 619 // registers have their original values. |
620 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 620 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, |
621 Handle<JSObject> object, | 621 Handle<JSObject> object, |
622 LookupResult* lookup, | 622 LookupResult* lookup, |
623 Register receiver_reg, | 623 Register receiver_reg, |
624 Register name_reg, | 624 Register name_reg, |
625 Register value_reg, | 625 Register value_reg, |
626 Register scratch1, | 626 Register scratch1, |
627 Register scratch2, | 627 Register scratch2, |
628 Label* miss_label) { | 628 Label* miss_label) { |
629 // r0 : value | 629 // r0 : value |
630 Label exit; | 630 Label exit; |
631 | 631 |
632 // Stub never generated for non-global objects that require access | 632 // Stub never generated for non-global objects that require access |
633 // checks. | 633 // checks. |
634 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 634 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
635 | 635 |
636 int index = lookup->GetFieldIndex().field_index(); | 636 int index = lookup->GetFieldIndex().field_index(); |
637 | 637 |
638 // Adjust for the number of properties stored in the object. Even in the | 638 // Adjust for the number of properties stored in the object. Even in the |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 } | 729 } |
730 } | 730 } |
731 | 731 |
732 // Return the value (register r0). | 732 // Return the value (register r0). |
733 ASSERT(value_reg.is(r0)); | 733 ASSERT(value_reg.is(r0)); |
734 __ bind(&exit); | 734 __ bind(&exit); |
735 __ Ret(); | 735 __ Ret(); |
736 } | 736 } |
737 | 737 |
738 | 738 |
739 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 739 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
740 Label* label, | 740 Label* label, |
741 Handle<Name> name) { | 741 Handle<Name> name) { |
742 if (!label->is_unused()) { | 742 if (!label->is_unused()) { |
743 __ bind(label); | 743 __ bind(label); |
744 __ mov(this->name(), Operand(name)); | 744 __ mov(this->name(), Operand(name)); |
745 } | 745 } |
746 } | 746 } |
747 | 747 |
748 | 748 |
749 static void GenerateCallFunction(MacroAssembler* masm, | 749 static void GenerateCallFunction(MacroAssembler* masm, |
750 Handle<Object> object, | 750 Handle<Object> object, |
751 const ParameterCount& arguments, | 751 const ParameterCount& arguments, |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 // If we've skipped any global objects, it's not enough to verify that | 1297 // If we've skipped any global objects, it's not enough to verify that |
1298 // their maps haven't changed. We also need to check that the property | 1298 // their maps haven't changed. We also need to check that the property |
1299 // cell for the property is still empty. | 1299 // cell for the property is still empty. |
1300 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1300 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
1301 | 1301 |
1302 // Return the register containing the holder. | 1302 // Return the register containing the holder. |
1303 return reg; | 1303 return reg; |
1304 } | 1304 } |
1305 | 1305 |
1306 | 1306 |
1307 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1307 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
1308 Label* success, | 1308 Label* success, |
1309 Label* miss) { | 1309 Label* miss) { |
1310 if (!miss->is_unused()) { | 1310 if (!miss->is_unused()) { |
1311 __ b(success); | 1311 __ b(success); |
1312 __ bind(miss); | 1312 __ bind(miss); |
1313 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1313 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1314 } | 1314 } |
1315 } | 1315 } |
1316 | 1316 |
1317 | 1317 |
1318 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1318 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
1319 Label* success, | 1319 Label* success, |
1320 Label* miss) { | 1320 Label* miss) { |
1321 if (!miss->is_unused()) { | 1321 if (!miss->is_unused()) { |
1322 __ b(success); | 1322 __ b(success); |
1323 GenerateRestoreName(masm(), miss, name); | 1323 GenerateRestoreName(masm(), miss, name); |
1324 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1324 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1325 } | 1325 } |
1326 } | 1326 } |
1327 | 1327 |
1328 | 1328 |
1329 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1329 Register LoadStubCompiler::CallbackHandlerFrontend( |
1330 Handle<JSObject> object, | 1330 Handle<JSObject> object, |
1331 Register object_reg, | 1331 Register object_reg, |
1332 Handle<JSObject> holder, | 1332 Handle<JSObject> holder, |
1333 Handle<Name> name, | 1333 Handle<Name> name, |
1334 Label* success, | 1334 Label* success, |
1335 Handle<Object> callback) { | 1335 Handle<Object> callback) { |
1336 Label miss; | 1336 Label miss; |
1337 | 1337 |
1338 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1338 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
1339 | 1339 |
(...skipping 26 matching lines...) Expand all Loading... |
1366 __ ldr(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 1366 __ ldr(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
1367 __ cmp(scratch2(), Operand(callback)); | 1367 __ cmp(scratch2(), Operand(callback)); |
1368 __ b(ne, &miss); | 1368 __ b(ne, &miss); |
1369 } | 1369 } |
1370 | 1370 |
1371 HandlerFrontendFooter(name, success, &miss); | 1371 HandlerFrontendFooter(name, success, &miss); |
1372 return reg; | 1372 return reg; |
1373 } | 1373 } |
1374 | 1374 |
1375 | 1375 |
1376 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1376 void LoadStubCompiler::NonexistentHandlerFrontend( |
1377 Handle<JSObject> object, | 1377 Handle<JSObject> object, |
1378 Handle<JSObject> last, | 1378 Handle<JSObject> last, |
1379 Handle<Name> name, | 1379 Handle<Name> name, |
1380 Label* success, | 1380 Label* success, |
1381 Handle<GlobalObject> global) { | 1381 Handle<GlobalObject> global) { |
1382 Label miss; | 1382 Label miss; |
1383 | 1383 |
1384 HandlerFrontendHeader(object, receiver(), last, name, &miss); | 1384 HandlerFrontendHeader(object, receiver(), last, name, &miss); |
1385 | 1385 |
1386 // If the last object in the prototype chain is a global object, | 1386 // If the last object in the prototype chain is a global object, |
1387 // check that the global property cell is empty. | 1387 // check that the global property cell is empty. |
1388 if (!global.is_null()) { | 1388 if (!global.is_null()) { |
1389 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1389 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
1390 } | 1390 } |
1391 | 1391 |
1392 HandlerFrontendFooter(name, success, &miss); | 1392 HandlerFrontendFooter(name, success, &miss); |
1393 } | 1393 } |
1394 | 1394 |
1395 | 1395 |
1396 void BaseLoadStubCompiler::GenerateLoadField(Register reg, | 1396 void LoadStubCompiler::GenerateLoadField(Register reg, |
1397 Handle<JSObject> holder, | 1397 Handle<JSObject> holder, |
1398 PropertyIndex field, | 1398 PropertyIndex field, |
1399 Representation representation) { | 1399 Representation representation) { |
1400 if (!reg.is(receiver())) __ mov(receiver(), reg); | 1400 if (!reg.is(receiver())) __ mov(receiver(), reg); |
1401 if (kind() == Code::LOAD_IC) { | 1401 if (kind() == Code::LOAD_IC) { |
1402 LoadFieldStub stub(field.is_inobject(holder), | 1402 LoadFieldStub stub(field.is_inobject(holder), |
1403 field.translate(holder), | 1403 field.translate(holder), |
1404 representation); | 1404 representation); |
1405 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1405 GenerateTailCall(masm(), stub.GetCode(isolate())); |
1406 } else { | 1406 } else { |
1407 KeyedLoadFieldStub stub(field.is_inobject(holder), | 1407 KeyedLoadFieldStub stub(field.is_inobject(holder), |
1408 field.translate(holder), | 1408 field.translate(holder), |
1409 representation); | 1409 representation); |
1410 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1410 GenerateTailCall(masm(), stub.GetCode(isolate())); |
1411 } | 1411 } |
1412 } | 1412 } |
1413 | 1413 |
1414 | 1414 |
1415 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1415 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
1416 // Return the constant value. | 1416 // Return the constant value. |
1417 __ LoadObject(r0, value); | 1417 __ LoadObject(r0, value); |
1418 __ Ret(); | 1418 __ Ret(); |
1419 } | 1419 } |
1420 | 1420 |
1421 | 1421 |
1422 void BaseLoadStubCompiler::GenerateLoadCallback( | 1422 void LoadStubCompiler::GenerateLoadCallback( |
1423 const CallOptimization& call_optimization) { | 1423 const CallOptimization& call_optimization) { |
1424 GenerateFastApiCall( | 1424 GenerateFastApiCall( |
1425 masm(), call_optimization, receiver(), scratch3(), 0, NULL); | 1425 masm(), call_optimization, receiver(), scratch3(), 0, NULL); |
1426 } | 1426 } |
1427 | 1427 |
1428 | 1428 |
1429 void BaseLoadStubCompiler::GenerateLoadCallback( | 1429 void LoadStubCompiler::GenerateLoadCallback( |
1430 Register reg, | 1430 Register reg, |
1431 Handle<ExecutableAccessorInfo> callback) { | 1431 Handle<ExecutableAccessorInfo> callback) { |
1432 // Build AccessorInfo::args_ list on the stack and push property name below | 1432 // Build AccessorInfo::args_ list on the stack and push property name below |
1433 // the exit frame to make GC aware of them and store pointers to them. | 1433 // the exit frame to make GC aware of them and store pointers to them. |
1434 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 1434 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
1435 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 1435 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
1436 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 1436 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
1437 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 1437 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
1438 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 1438 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
1439 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 1439 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1485 __ CallApiFunctionAndReturn(ref, | 1485 __ CallApiFunctionAndReturn(ref, |
1486 getter_address, | 1486 getter_address, |
1487 thunk_ref, | 1487 thunk_ref, |
1488 r2, | 1488 r2, |
1489 kStackUnwindSpace, | 1489 kStackUnwindSpace, |
1490 MemOperand(fp, 6 * kPointerSize), | 1490 MemOperand(fp, 6 * kPointerSize), |
1491 NULL); | 1491 NULL); |
1492 } | 1492 } |
1493 | 1493 |
1494 | 1494 |
1495 void BaseLoadStubCompiler::GenerateLoadInterceptor( | 1495 void LoadStubCompiler::GenerateLoadInterceptor( |
1496 Register holder_reg, | 1496 Register holder_reg, |
1497 Handle<JSObject> object, | 1497 Handle<JSObject> object, |
1498 Handle<JSObject> interceptor_holder, | 1498 Handle<JSObject> interceptor_holder, |
1499 LookupResult* lookup, | 1499 LookupResult* lookup, |
1500 Handle<Name> name) { | 1500 Handle<Name> name) { |
1501 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1501 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1502 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1502 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1503 | 1503 |
1504 // So far the most popular follow ups for interceptor loads are FIELD | 1504 // So far the most popular follow ups for interceptor loads are FIELD |
1505 // and CALLBACKS, so inline only them, other cases may be added | 1505 // and CALLBACKS, so inline only them, other cases may be added |
(...skipping 1491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2997 __ cmp(name_reg, Operand(name)); | 2997 __ cmp(name_reg, Operand(name)); |
2998 __ b(ne, miss); | 2998 __ b(ne, miss); |
2999 } | 2999 } |
3000 | 3000 |
3001 | 3001 |
3002 #undef __ | 3002 #undef __ |
3003 #define __ ACCESS_MASM(masm) | 3003 #define __ ACCESS_MASM(masm) |
3004 | 3004 |
3005 | 3005 |
3006 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 3006 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
| 3007 Register receiver, |
3007 Handle<JSFunction> getter) { | 3008 Handle<JSFunction> getter) { |
3008 // ----------- S t a t e ------------- | 3009 // ----------- S t a t e ------------- |
3009 // -- r0 : receiver | 3010 // -- r0 : receiver |
3010 // -- r2 : name | 3011 // -- r2 : name |
3011 // -- lr : return address | 3012 // -- lr : return address |
3012 // ----------------------------------- | 3013 // ----------------------------------- |
3013 { | 3014 { |
3014 FrameScope scope(masm, StackFrame::INTERNAL); | 3015 FrameScope scope(masm, StackFrame::INTERNAL); |
3015 | 3016 |
3016 if (!getter.is_null()) { | 3017 if (!getter.is_null()) { |
3017 // Call the JavaScript getter with the receiver on the stack. | 3018 // Call the JavaScript getter with the receiver on the stack. |
3018 __ push(r0); | 3019 __ push(receiver); |
3019 ParameterCount actual(0); | 3020 ParameterCount actual(0); |
3020 ParameterCount expected(getter); | 3021 ParameterCount expected(getter); |
3021 __ InvokeFunction(getter, expected, actual, | 3022 __ InvokeFunction(getter, expected, actual, |
3022 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 3023 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
3023 } else { | 3024 } else { |
3024 // If we generate a global code snippet for deoptimization only, remember | 3025 // If we generate a global code snippet for deoptimization only, remember |
3025 // the place to continue after deoptimization. | 3026 // the place to continue after deoptimization. |
3026 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | 3027 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
3027 } | 3028 } |
3028 | 3029 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3188 // ----------------------------------- | 3189 // ----------------------------------- |
3189 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3190 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3190 } | 3191 } |
3191 | 3192 |
3192 | 3193 |
3193 #undef __ | 3194 #undef __ |
3194 | 3195 |
3195 } } // namespace v8::internal | 3196 } } // namespace v8::internal |
3196 | 3197 |
3197 #endif // V8_TARGET_ARCH_ARM | 3198 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |