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 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 Label* miss) { | 418 Label* miss) { |
419 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name); | 419 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name); |
420 ASSERT(cell->value()->IsTheHole()); | 420 ASSERT(cell->value()->IsTheHole()); |
421 __ li(scratch, Operand(cell)); | 421 __ li(scratch, Operand(cell)); |
422 __ lw(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 422 __ lw(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
423 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 423 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
424 __ Branch(miss, ne, scratch, Operand(at)); | 424 __ Branch(miss, ne, scratch, Operand(at)); |
425 } | 425 } |
426 | 426 |
427 | 427 |
428 void BaseStoreStubCompiler::GenerateNegativeHolderLookup( | 428 void StoreStubCompiler::GenerateNegativeHolderLookup( |
429 MacroAssembler* masm, | 429 MacroAssembler* masm, |
430 Handle<JSObject> holder, | 430 Handle<JSObject> holder, |
431 Register holder_reg, | 431 Register holder_reg, |
432 Handle<Name> name, | 432 Handle<Name> name, |
433 Label* miss) { | 433 Label* miss) { |
434 if (holder->IsJSGlobalObject()) { | 434 if (holder->IsJSGlobalObject()) { |
435 GenerateCheckPropertyCell( | 435 GenerateCheckPropertyCell( |
436 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); | 436 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); |
437 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 437 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
438 GenerateDictionaryNegativeLookup( | 438 GenerateDictionaryNegativeLookup( |
439 masm, miss, holder_reg, name, scratch1(), scratch2()); | 439 masm, miss, holder_reg, name, scratch1(), scratch2()); |
440 } | 440 } |
441 } | 441 } |
442 | 442 |
443 | 443 |
444 // Generate StoreTransition code, value is passed in a0 register. | 444 // Generate StoreTransition code, value is passed in a0 register. |
445 // After executing generated code, the receiver_reg and name_reg | 445 // After executing generated code, the receiver_reg and name_reg |
446 // may be clobbered. | 446 // may be clobbered. |
447 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 447 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
448 Handle<JSObject> object, | 448 Handle<JSObject> object, |
449 LookupResult* lookup, | 449 LookupResult* lookup, |
450 Handle<Map> transition, | 450 Handle<Map> transition, |
451 Handle<Name> name, | 451 Handle<Name> name, |
452 Register receiver_reg, | 452 Register receiver_reg, |
453 Register storage_reg, | 453 Register storage_reg, |
454 Register value_reg, | 454 Register value_reg, |
455 Register scratch1, | 455 Register scratch1, |
456 Register scratch2, | 456 Register scratch2, |
457 Register scratch3, | 457 Register scratch3, |
458 Label* miss_label, | 458 Label* miss_label, |
459 Label* slow) { | 459 Label* slow) { |
460 // a0 : value. | 460 // a0 : value. |
461 Label exit; | 461 Label exit; |
462 | 462 |
463 int descriptor = transition->LastAdded(); | 463 int descriptor = transition->LastAdded(); |
464 DescriptorArray* descriptors = transition->instance_descriptors(); | 464 DescriptorArray* descriptors = transition->instance_descriptors(); |
465 PropertyDetails details = descriptors->GetDetails(descriptor); | 465 PropertyDetails details = descriptors->GetDetails(descriptor); |
466 Representation representation = details.representation(); | 466 Representation representation = details.representation(); |
467 ASSERT(!representation.IsNone()); | 467 ASSERT(!representation.IsNone()); |
468 | 468 |
469 if (details.type() == CONSTANT) { | 469 if (details.type() == CONSTANT) { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 __ bind(&exit); | 601 __ bind(&exit); |
602 __ Ret(USE_DELAY_SLOT); | 602 __ Ret(USE_DELAY_SLOT); |
603 __ mov(v0, a0); | 603 __ mov(v0, a0); |
604 } | 604 } |
605 | 605 |
606 | 606 |
607 // Generate StoreField code, value is passed in a0 register. | 607 // Generate StoreField code, value is passed in a0 register. |
608 // When leaving generated code after success, the receiver_reg and name_reg | 608 // When leaving generated code after success, the receiver_reg and name_reg |
609 // may be clobbered. Upon branch to miss_label, the receiver and name | 609 // may be clobbered. Upon branch to miss_label, the receiver and name |
610 // registers have their original values. | 610 // registers have their original values. |
611 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 611 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, |
612 Handle<JSObject> object, | 612 Handle<JSObject> object, |
613 LookupResult* lookup, | 613 LookupResult* lookup, |
614 Register receiver_reg, | 614 Register receiver_reg, |
615 Register name_reg, | 615 Register name_reg, |
616 Register value_reg, | 616 Register value_reg, |
617 Register scratch1, | 617 Register scratch1, |
618 Register scratch2, | 618 Register scratch2, |
619 Label* miss_label) { | 619 Label* miss_label) { |
620 // a0 : value | 620 // a0 : value |
621 Label exit; | 621 Label exit; |
622 | 622 |
623 // Stub never generated for non-global objects that require access | 623 // Stub never generated for non-global objects that require access |
624 // checks. | 624 // checks. |
625 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 625 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
626 | 626 |
627 int index = lookup->GetFieldIndex().field_index(); | 627 int index = lookup->GetFieldIndex().field_index(); |
628 | 628 |
629 // Adjust for the number of properties stored in the object. Even in the | 629 // Adjust for the number of properties stored in the object. Even in the |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 } | 722 } |
723 | 723 |
724 // Return the value (register v0). | 724 // Return the value (register v0). |
725 ASSERT(value_reg.is(a0)); | 725 ASSERT(value_reg.is(a0)); |
726 __ bind(&exit); | 726 __ bind(&exit); |
727 __ Ret(USE_DELAY_SLOT); | 727 __ Ret(USE_DELAY_SLOT); |
728 __ mov(v0, a0); | 728 __ mov(v0, a0); |
729 } | 729 } |
730 | 730 |
731 | 731 |
732 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 732 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
733 Label* label, | 733 Label* label, |
734 Handle<Name> name) { | 734 Handle<Name> name) { |
735 if (!label->is_unused()) { | 735 if (!label->is_unused()) { |
736 __ bind(label); | 736 __ bind(label); |
737 __ li(this->name(), Operand(name)); | 737 __ li(this->name(), Operand(name)); |
738 } | 738 } |
739 } | 739 } |
740 | 740 |
741 | 741 |
742 static void GenerateCallFunction(MacroAssembler* masm, | 742 static void GenerateCallFunction(MacroAssembler* masm, |
743 Handle<Object> object, | 743 Handle<Object> object, |
744 const ParameterCount& arguments, | 744 const ParameterCount& arguments, |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1289 // If we've skipped any global objects, it's not enough to verify that | 1289 // If we've skipped any global objects, it's not enough to verify that |
1290 // their maps haven't changed. We also need to check that the property | 1290 // their maps haven't changed. We also need to check that the property |
1291 // cell for the property is still empty. | 1291 // cell for the property is still empty. |
1292 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1292 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
1293 | 1293 |
1294 // Return the register containing the holder. | 1294 // Return the register containing the holder. |
1295 return reg; | 1295 return reg; |
1296 } | 1296 } |
1297 | 1297 |
1298 | 1298 |
1299 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1299 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
1300 Label* success, | 1300 Label* success, |
1301 Label* miss) { | 1301 Label* miss) { |
1302 if (!miss->is_unused()) { | 1302 if (!miss->is_unused()) { |
1303 __ Branch(success); | 1303 __ Branch(success); |
1304 __ bind(miss); | 1304 __ bind(miss); |
1305 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1305 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1306 } | 1306 } |
1307 } | 1307 } |
1308 | 1308 |
1309 | 1309 |
1310 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1310 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
1311 Label* success, | 1311 Label* success, |
1312 Label* miss) { | 1312 Label* miss) { |
1313 if (!miss->is_unused()) { | 1313 if (!miss->is_unused()) { |
1314 __ b(success); | 1314 __ b(success); |
1315 GenerateRestoreName(masm(), miss, name); | 1315 GenerateRestoreName(masm(), miss, name); |
1316 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1316 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1317 } | 1317 } |
1318 } | 1318 } |
1319 | 1319 |
1320 | 1320 |
1321 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1321 Register LoadStubCompiler::CallbackHandlerFrontend( |
1322 Handle<JSObject> object, | 1322 Handle<JSObject> object, |
1323 Register object_reg, | 1323 Register object_reg, |
1324 Handle<JSObject> holder, | 1324 Handle<JSObject> holder, |
1325 Handle<Name> name, | 1325 Handle<Name> name, |
1326 Label* success, | 1326 Label* success, |
1327 Handle<Object> callback) { | 1327 Handle<Object> callback) { |
1328 Label miss; | 1328 Label miss; |
1329 | 1329 |
1330 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1330 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
1331 | 1331 |
(...skipping 25 matching lines...) Expand all Loading... |
1357 const int kValueOffset = kElementsStartOffset + kPointerSize; | 1357 const int kValueOffset = kElementsStartOffset + kPointerSize; |
1358 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 1358 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
1359 __ Branch(&miss, ne, scratch2(), Operand(callback)); | 1359 __ Branch(&miss, ne, scratch2(), Operand(callback)); |
1360 } | 1360 } |
1361 | 1361 |
1362 HandlerFrontendFooter(name, success, &miss); | 1362 HandlerFrontendFooter(name, success, &miss); |
1363 return reg; | 1363 return reg; |
1364 } | 1364 } |
1365 | 1365 |
1366 | 1366 |
1367 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1367 void LoadStubCompiler::NonexistentHandlerFrontend( |
1368 Handle<JSObject> object, | 1368 Handle<JSObject> object, |
1369 Handle<JSObject> last, | 1369 Handle<JSObject> last, |
1370 Handle<Name> name, | 1370 Handle<Name> name, |
1371 Label* success, | 1371 Label* success, |
1372 Handle<GlobalObject> global) { | 1372 Handle<GlobalObject> global) { |
1373 Label miss; | 1373 Label miss; |
1374 | 1374 |
1375 HandlerFrontendHeader(object, receiver(), last, name, &miss); | 1375 HandlerFrontendHeader(object, receiver(), last, name, &miss); |
1376 | 1376 |
1377 // If the last object in the prototype chain is a global object, | 1377 // If the last object in the prototype chain is a global object, |
1378 // check that the global property cell is empty. | 1378 // check that the global property cell is empty. |
1379 if (!global.is_null()) { | 1379 if (!global.is_null()) { |
1380 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1380 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
1381 } | 1381 } |
1382 | 1382 |
1383 HandlerFrontendFooter(name, success, &miss); | 1383 HandlerFrontendFooter(name, success, &miss); |
1384 } | 1384 } |
1385 | 1385 |
1386 | 1386 |
1387 void BaseLoadStubCompiler::GenerateLoadField(Register reg, | 1387 void LoadStubCompiler::GenerateLoadField(Register reg, |
1388 Handle<JSObject> holder, | 1388 Handle<JSObject> holder, |
1389 PropertyIndex field, | 1389 PropertyIndex field, |
1390 Representation representation) { | 1390 Representation representation) { |
1391 if (!reg.is(receiver())) __ mov(receiver(), reg); | 1391 if (!reg.is(receiver())) __ mov(receiver(), reg); |
1392 if (kind() == Code::LOAD_IC) { | 1392 if (kind() == Code::LOAD_IC) { |
1393 LoadFieldStub stub(field.is_inobject(holder), | 1393 LoadFieldStub stub(field.is_inobject(holder), |
1394 field.translate(holder), | 1394 field.translate(holder), |
1395 representation); | 1395 representation); |
1396 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1396 GenerateTailCall(masm(), stub.GetCode(isolate())); |
1397 } else { | 1397 } else { |
1398 KeyedLoadFieldStub stub(field.is_inobject(holder), | 1398 KeyedLoadFieldStub stub(field.is_inobject(holder), |
1399 field.translate(holder), | 1399 field.translate(holder), |
1400 representation); | 1400 representation); |
1401 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1401 GenerateTailCall(masm(), stub.GetCode(isolate())); |
1402 } | 1402 } |
1403 } | 1403 } |
1404 | 1404 |
1405 | 1405 |
1406 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1406 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
1407 // Return the constant value. | 1407 // Return the constant value. |
1408 __ LoadObject(v0, value); | 1408 __ LoadObject(v0, value); |
1409 __ Ret(); | 1409 __ Ret(); |
1410 } | 1410 } |
1411 | 1411 |
1412 | 1412 |
1413 void BaseLoadStubCompiler::GenerateLoadCallback( | 1413 void LoadStubCompiler::GenerateLoadCallback( |
1414 const CallOptimization& call_optimization) { | 1414 const CallOptimization& call_optimization) { |
1415 GenerateFastApiCall( | 1415 GenerateFastApiCall( |
1416 masm(), call_optimization, receiver(), scratch3(), 0, NULL); | 1416 masm(), call_optimization, receiver(), scratch3(), 0, NULL); |
1417 } | 1417 } |
1418 | 1418 |
1419 | 1419 |
1420 void BaseLoadStubCompiler::GenerateLoadCallback( | 1420 void LoadStubCompiler::GenerateLoadCallback( |
1421 Register reg, | 1421 Register reg, |
1422 Handle<ExecutableAccessorInfo> callback) { | 1422 Handle<ExecutableAccessorInfo> callback) { |
1423 // Build AccessorInfo::args_ list on the stack and push property name below | 1423 // Build AccessorInfo::args_ list on the stack and push property name below |
1424 // the exit frame to make GC aware of them and store pointers to them. | 1424 // the exit frame to make GC aware of them and store pointers to them. |
1425 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 1425 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
1426 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 1426 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
1427 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 1427 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
1428 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 1428 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
1429 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 1429 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
1430 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 1430 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1480 __ CallApiFunctionAndReturn(ref, | 1480 __ CallApiFunctionAndReturn(ref, |
1481 getter_address, | 1481 getter_address, |
1482 thunk_ref, | 1482 thunk_ref, |
1483 a2, | 1483 a2, |
1484 kStackUnwindSpace, | 1484 kStackUnwindSpace, |
1485 MemOperand(fp, 6 * kPointerSize), | 1485 MemOperand(fp, 6 * kPointerSize), |
1486 NULL); | 1486 NULL); |
1487 } | 1487 } |
1488 | 1488 |
1489 | 1489 |
1490 void BaseLoadStubCompiler::GenerateLoadInterceptor( | 1490 void LoadStubCompiler::GenerateLoadInterceptor( |
1491 Register holder_reg, | 1491 Register holder_reg, |
1492 Handle<JSObject> object, | 1492 Handle<JSObject> object, |
1493 Handle<JSObject> interceptor_holder, | 1493 Handle<JSObject> interceptor_holder, |
1494 LookupResult* lookup, | 1494 LookupResult* lookup, |
1495 Handle<Name> name) { | 1495 Handle<Name> name) { |
1496 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1496 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1497 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1497 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1498 | 1498 |
1499 // So far the most popular follow ups for interceptor loads are FIELD | 1499 // So far the most popular follow ups for interceptor loads are FIELD |
1500 // and CALLBACKS, so inline only them, other cases may be added | 1500 // and CALLBACKS, so inline only them, other cases may be added |
(...skipping 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3012 Label* miss) { | 3012 Label* miss) { |
3013 __ Branch(miss, ne, name_reg, Operand(name)); | 3013 __ Branch(miss, ne, name_reg, Operand(name)); |
3014 } | 3014 } |
3015 | 3015 |
3016 | 3016 |
3017 #undef __ | 3017 #undef __ |
3018 #define __ ACCESS_MASM(masm) | 3018 #define __ ACCESS_MASM(masm) |
3019 | 3019 |
3020 | 3020 |
3021 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 3021 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
| 3022 Register receiver, |
3022 Handle<JSFunction> getter) { | 3023 Handle<JSFunction> getter) { |
3023 // ----------- S t a t e ------------- | 3024 // ----------- S t a t e ------------- |
3024 // -- a0 : receiver | 3025 // -- a0 : receiver |
3025 // -- a2 : name | 3026 // -- a2 : name |
3026 // -- ra : return address | 3027 // -- ra : return address |
3027 // ----------------------------------- | 3028 // ----------------------------------- |
3028 { | 3029 { |
3029 FrameScope scope(masm, StackFrame::INTERNAL); | 3030 FrameScope scope(masm, StackFrame::INTERNAL); |
3030 | 3031 |
3031 if (!getter.is_null()) { | 3032 if (!getter.is_null()) { |
3032 // Call the JavaScript getter with the receiver on the stack. | 3033 // Call the JavaScript getter with the receiver on the stack. |
3033 __ push(a0); | 3034 __ push(receiver); |
3034 ParameterCount actual(0); | 3035 ParameterCount actual(0); |
3035 ParameterCount expected(getter); | 3036 ParameterCount expected(getter); |
3036 __ InvokeFunction(getter, expected, actual, | 3037 __ InvokeFunction(getter, expected, actual, |
3037 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 3038 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
3038 } else { | 3039 } else { |
3039 // If we generate a global code snippet for deoptimization only, remember | 3040 // If we generate a global code snippet for deoptimization only, remember |
3040 // the place to continue after deoptimization. | 3041 // the place to continue after deoptimization. |
3041 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | 3042 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
3042 } | 3043 } |
3043 | 3044 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3202 // ----------------------------------- | 3203 // ----------------------------------- |
3203 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3204 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3204 } | 3205 } |
3205 | 3206 |
3206 | 3207 |
3207 #undef __ | 3208 #undef __ |
3208 | 3209 |
3209 } } // namespace v8::internal | 3210 } } // namespace v8::internal |
3210 | 3211 |
3211 #endif // V8_TARGET_ARCH_MIPS | 3212 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |