| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 | 325 |
| 326 | 326 |
| 327 // Generate code to load the length from a string object and return the length. | 327 // Generate code to load the length from a string object and return the length. |
| 328 // If the receiver object is not a string or a wrapped string object the | 328 // If the receiver object is not a string or a wrapped string object the |
| 329 // execution continues at the miss label. The register containing the | 329 // execution continues at the miss label. The register containing the |
| 330 // receiver is not clobbered if the receiver is not a string. | 330 // receiver is not clobbered if the receiver is not a string. |
| 331 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 331 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, |
| 332 Register receiver, | 332 Register receiver, |
| 333 Register scratch1, | 333 Register scratch1, |
| 334 Register scratch2, | 334 Register scratch2, |
| 335 Label* miss, | 335 Label* miss) { |
| 336 bool support_wrappers) { | |
| 337 // Input registers can't alias because we don't want to clobber the | 336 // Input registers can't alias because we don't want to clobber the |
| 338 // receiver register if the object is not a string. | 337 // receiver register if the object is not a string. |
| 339 ASSERT(!AreAliased(receiver, scratch1, scratch2)); | 338 ASSERT(!AreAliased(receiver, scratch1, scratch2)); |
| 340 | 339 |
| 341 Label check_wrapper; | 340 Label check_wrapper; |
| 342 | 341 |
| 343 // Check if the object is a string leaving the instance type in the | 342 // Check if the object is a string leaving the instance type in the |
| 344 // scratch1 register. | 343 // scratch1 register. |
| 345 GenerateStringCheck(masm, receiver, scratch1, miss, | 344 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); |
| 346 support_wrappers ? &check_wrapper : miss); | |
| 347 | 345 |
| 348 // Load length directly from the string. | 346 // Load length directly from the string. |
| 349 __ Ldr(x0, FieldMemOperand(receiver, String::kLengthOffset)); | 347 __ Ldr(x0, FieldMemOperand(receiver, String::kLengthOffset)); |
| 350 __ Ret(); | 348 __ Ret(); |
| 351 | 349 |
| 352 if (support_wrappers) { | 350 // Check if the object is a JSValue wrapper. |
| 353 // Check if the object is a JSValue wrapper. | 351 __ Bind(&check_wrapper); |
| 354 __ Bind(&check_wrapper); | 352 __ Cmp(scratch1, Operand(JS_VALUE_TYPE)); |
| 355 __ Cmp(scratch1, Operand(JS_VALUE_TYPE)); | 353 __ B(ne, miss); |
| 356 __ B(ne, miss); | |
| 357 | 354 |
| 358 // Unwrap the value and check if the wrapped value is a string. | 355 // Unwrap the value and check if the wrapped value is a string. |
| 359 __ Ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset)); | 356 __ Ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset)); |
| 360 GenerateStringCheck(masm, scratch1, scratch2, miss, miss); | 357 GenerateStringCheck(masm, scratch1, scratch2, miss, miss); |
| 361 __ Ldr(x0, FieldMemOperand(scratch1, String::kLengthOffset)); | 358 __ Ldr(x0, FieldMemOperand(scratch1, String::kLengthOffset)); |
| 362 __ Ret(); | 359 __ Ret(); |
| 363 } | |
| 364 } | 360 } |
| 365 | 361 |
| 366 | 362 |
| 367 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 363 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, |
| 368 Register receiver, | 364 Register receiver, |
| 369 Register scratch1, | 365 Register scratch1, |
| 370 Register scratch2, | 366 Register scratch2, |
| 371 Label* miss_label) { | 367 Label* miss_label) { |
| 372 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 368 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 373 // TryGetFunctionPrototype can't put the result directly in x0 because the | 369 // TryGetFunctionPrototype can't put the result directly in x0 because the |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 __ InvokeFunction( | 772 __ InvokeFunction( |
| 777 function, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | 773 function, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 778 } | 774 } |
| 779 | 775 |
| 780 | 776 |
| 781 static void PushInterceptorArguments(MacroAssembler* masm, | 777 static void PushInterceptorArguments(MacroAssembler* masm, |
| 782 Register receiver, | 778 Register receiver, |
| 783 Register holder, | 779 Register holder, |
| 784 Register name, | 780 Register name, |
| 785 Handle<JSObject> holder_obj) { | 781 Handle<JSObject> holder_obj) { |
| 782 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
| 783 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
| 784 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
| 785 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
| 786 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
| 787 |
| 786 __ Push(name); | 788 __ Push(name); |
| 787 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 789 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 788 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 790 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 789 Register scratch = name; | 791 Register scratch = name; |
| 790 __ Mov(scratch, Operand(interceptor)); | 792 __ Mov(scratch, Operand(interceptor)); |
| 791 __ Push(scratch, receiver, holder); | 793 __ Push(scratch, receiver, holder); |
| 792 __ Ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); | |
| 793 __ Push(scratch); | |
| 794 __ Mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate()))); | |
| 795 __ Push(scratch); | |
| 796 } | 794 } |
| 797 | 795 |
| 798 | 796 |
| 799 static void CompileCallLoadPropertyWithInterceptor( | 797 static void CompileCallLoadPropertyWithInterceptor( |
| 800 MacroAssembler* masm, | 798 MacroAssembler* masm, |
| 801 Register receiver, | 799 Register receiver, |
| 802 Register holder, | 800 Register holder, |
| 803 Register name, | 801 Register name, |
| 804 Handle<JSObject> holder_obj) { | 802 Handle<JSObject> holder_obj) { |
| 805 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 803 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 806 | 804 |
| 807 ExternalReference ref = | 805 ExternalReference ref = |
| 808 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 806 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
| 809 masm->isolate()); | 807 masm->isolate()); |
| 810 // Put the number of on-stack arguments for runtime call in x0. | 808 // Put the number of on-stack arguments for runtime call in x0. |
| 811 // These arguemnts have been pushed by PushInterceptorArguments. | 809 // These arguemnts have been pushed by PushInterceptorArguments. |
| 812 __ Mov(x0, 6); | 810 __ Mov(x0, StubCache::kInterceptorArgsLength); |
| 813 __ Mov(x1, Operand(ref)); | 811 __ Mov(x1, Operand(ref)); |
| 814 | 812 |
| 815 CEntryStub stub(1); | 813 CEntryStub stub(1); |
| 816 __ CallStub(&stub); | 814 __ CallStub(&stub); |
| 817 } | 815 } |
| 818 | 816 |
| 819 | 817 |
| 820 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 818 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; |
| 821 | 819 |
| 822 // Reserves space for the extra arguments to API function in the | 820 // Reserves space for the extra arguments to API function in the |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1127 name, miss_label); | 1125 name, miss_label); |
| 1128 | 1126 |
| 1129 // Call a runtime function to load the interceptor property. | 1127 // Call a runtime function to load the interceptor property. |
| 1130 FrameScope scope(masm, StackFrame::INTERNAL); | 1128 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1131 // The name_ register must be preserved across the call. | 1129 // The name_ register must be preserved across the call. |
| 1132 __ Push(name_); | 1130 __ Push(name_); |
| 1133 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 1131 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
| 1134 __ CallExternalReference( | 1132 __ CallExternalReference( |
| 1135 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 1133 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
| 1136 masm->isolate()), | 1134 masm->isolate()), |
| 1137 6); | 1135 StubCache::kInterceptorArgsLength); |
| 1138 __ Pop(name_); | 1136 __ Pop(name_); |
| 1139 } | 1137 } |
| 1140 | 1138 |
| 1141 | 1139 |
| 1142 void LoadWithInterceptor(MacroAssembler* masm, | 1140 void LoadWithInterceptor(MacroAssembler* masm, |
| 1143 Register receiver, | 1141 Register receiver, |
| 1144 Register holder, | 1142 Register holder, |
| 1145 Handle<JSObject> holder_obj, | 1143 Handle<JSObject> holder_obj, |
| 1146 Register scratch, | 1144 Register scratch, |
| 1147 Label* interceptor_succeeded) { | 1145 Label* interceptor_succeeded) { |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 void BaseLoadStubCompiler::GenerateLoadCallback( | 1415 void BaseLoadStubCompiler::GenerateLoadCallback( |
| 1418 const CallOptimization& call_optimization) { | 1416 const CallOptimization& call_optimization) { |
| 1419 GenerateFastApiCall( | 1417 GenerateFastApiCall( |
| 1420 masm(), call_optimization, receiver(), scratch3(), 0, NULL); | 1418 masm(), call_optimization, receiver(), scratch3(), 0, NULL); |
| 1421 } | 1419 } |
| 1422 | 1420 |
| 1423 | 1421 |
| 1424 void BaseLoadStubCompiler::GenerateLoadCallback( | 1422 void BaseLoadStubCompiler::GenerateLoadCallback( |
| 1425 Register reg, | 1423 Register reg, |
| 1426 Handle<ExecutableAccessorInfo> callback) { | 1424 Handle<ExecutableAccessorInfo> callback) { |
| 1425 ASSERT(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); |
| 1426 |
| 1427 // Build ExecutableAccessorInfo::args_ list on the stack and push property | 1427 // Build ExecutableAccessorInfo::args_ list on the stack and push property |
| 1428 // name below the exit frame to make GC aware of them and store pointers to | 1428 // name below the exit frame to make GC aware of them and store pointers to |
| 1429 // them. | 1429 // them. |
| 1430 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 0); |
| 1431 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == -1); |
| 1432 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == -2); |
| 1433 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == -3); |
| 1434 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == -4); |
| 1435 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == -5); |
| 1436 |
| 1430 __ Push(receiver()); | 1437 __ Push(receiver()); |
| 1431 Register args_addr = scratch2(); | 1438 Register args_addr = scratch2(); |
| 1432 __ Mov(args_addr, __ StackPointer()); | 1439 __ Mov(args_addr, __ StackPointer()); |
| 1433 | 1440 |
| 1434 if (heap()->InNewSpace(callback->data())) { | 1441 if (heap()->InNewSpace(callback->data())) { |
| 1435 __ Mov(scratch3(), Operand(callback)); | 1442 __ Mov(scratch3(), Operand(callback)); |
| 1436 __ Ldr(scratch3(), FieldMemOperand(scratch3(), | 1443 __ Ldr(scratch3(), FieldMemOperand(scratch3(), |
| 1437 ExecutableAccessorInfo::kDataOffset)); | 1444 ExecutableAccessorInfo::kDataOffset)); |
| 1438 } else { | 1445 } else { |
| 1439 __ Mov(scratch3(), Operand(Handle<Object>(callback->data(), isolate()))); | 1446 __ Mov(scratch3(), Operand(Handle<Object>(callback->data(), isolate()))); |
| 1440 } | 1447 } |
| 1441 // TODO(jbramley): Find another scratch register and combine the pushes | 1448 // TODO(jbramley): Find another scratch register and combine the pushes |
| 1442 // together. Can we use scratch1() and scratch2() here? | 1449 // together. Can we use scratch1() here? |
| 1443 __ Push(reg, scratch3()); | 1450 // Push: |
| 1444 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); | 1451 // - callback data |
| 1445 __ Mov(scratch4(), Operand(ExternalReference::isolate_address(isolate()))); | 1452 // - undefined |
| 1446 __ Push(scratch3(), scratch3(), scratch4(), name()); | 1453 // - undefined |
| 1454 // - isolate |
| 1455 // - reg |
| 1456 // - name |
| 1457 __ LoadRoot(scratch4(), Heap::kUndefinedValueRootIndex); |
| 1458 __ Push(scratch3(), scratch4()); |
| 1459 __ Mov(scratch3(), Operand(ExternalReference::isolate_address(isolate()))); |
| 1460 __ Push(scratch4(), scratch3(), reg, name()); |
| 1447 | 1461 |
| 1448 // Pass the Handle<Name> of the property name to the runtime. | 1462 // Pass the Handle<Name> of the property name to the runtime. |
| 1449 __ Mov(x0, __ StackPointer()); | 1463 __ Mov(x0, __ StackPointer()); |
| 1450 | 1464 |
| 1451 FrameScope frame_scope(masm(), StackFrame::MANUAL); | 1465 FrameScope frame_scope(masm(), StackFrame::MANUAL); |
| 1452 const int kApiStackSpace = 1; | 1466 const int kApiStackSpace = 1; |
| 1453 __ EnterExitFrame(false, scratch4(), | 1467 __ EnterExitFrame(false, scratch4(), |
| 1454 kApiStackSpace + MacroAssembler::kCallApiFunctionSpillSpace); | 1468 kApiStackSpace + MacroAssembler::kCallApiFunctionSpillSpace); |
| 1455 | 1469 |
| 1456 // Create ExecutableAccessorInfo instance on the stack above the exit frame | 1470 // Create ExecutableAccessorInfo instance on the stack above the exit frame |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1483 ApiFunction fun(getter_address); | 1497 ApiFunction fun(getter_address); |
| 1484 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 1498 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
| 1485 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 1499 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
| 1486 | 1500 |
| 1487 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1501 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
| 1488 ExternalReference::Type thunk_type = ExternalReference::PROFILING_GETTER_CALL; | 1502 ExternalReference::Type thunk_type = ExternalReference::PROFILING_GETTER_CALL; |
| 1489 ApiFunction thunk_fun(thunk_address); | 1503 ApiFunction thunk_fun(thunk_address); |
| 1490 ExternalReference thunk_ref = | 1504 ExternalReference thunk_ref = |
| 1491 ExternalReference(&thunk_fun, thunk_type, isolate()); | 1505 ExternalReference(&thunk_fun, thunk_type, isolate()); |
| 1492 | 1506 |
| 1493 // TODO(jbramley): I don't know where '5' comes from, but this goes away at | 1507 // TODO(jbramley): I don't know where '6' comes from, but this goes away at |
| 1494 // some point. | 1508 // some point. |
| 1495 __ CallApiFunctionAndReturn(ref, | 1509 __ CallApiFunctionAndReturn(ref, |
| 1496 getter_address, | 1510 getter_address, |
| 1497 thunk_ref, | 1511 thunk_ref, |
| 1498 x2, | 1512 x2, |
| 1499 kStackUnwindSpace, | 1513 kStackUnwindSpace, |
| 1500 spill_offset, | 1514 spill_offset, |
| 1501 5); | 1515 6); |
| 1502 } | 1516 } |
| 1503 | 1517 |
| 1504 | 1518 |
| 1505 void BaseLoadStubCompiler::GenerateLoadInterceptor( | 1519 void BaseLoadStubCompiler::GenerateLoadInterceptor( |
| 1506 Register holder_reg, | 1520 Register holder_reg, |
| 1507 Handle<JSObject> object, | 1521 Handle<JSObject> object, |
| 1508 Handle<JSObject> interceptor_holder, | 1522 Handle<JSObject> interceptor_holder, |
| 1509 LookupResult* lookup, | 1523 LookupResult* lookup, |
| 1510 Handle<Name> name) { | 1524 Handle<Name> name) { |
| 1511 ASSERT(!AreAliased(receiver(), this->name(), | 1525 ASSERT(!AreAliased(receiver(), this->name(), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1579 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 1593 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); |
| 1580 } else { // !compile_followup_inline | 1594 } else { // !compile_followup_inline |
| 1581 // Call the runtime system to load the interceptor. | 1595 // Call the runtime system to load the interceptor. |
| 1582 // Check that the maps haven't changed. | 1596 // Check that the maps haven't changed. |
| 1583 PushInterceptorArguments( | 1597 PushInterceptorArguments( |
| 1584 masm(), receiver(), holder_reg, this->name(), interceptor_holder); | 1598 masm(), receiver(), holder_reg, this->name(), interceptor_holder); |
| 1585 | 1599 |
| 1586 ExternalReference ref = | 1600 ExternalReference ref = |
| 1587 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1601 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
| 1588 isolate()); | 1602 isolate()); |
| 1589 __ TailCallExternalReference(ref, 6, 1); | 1603 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
| 1590 } | 1604 } |
| 1591 } | 1605 } |
| 1592 | 1606 |
| 1593 | 1607 |
| 1594 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1608 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1595 Register name_reg = x2; | 1609 Register name_reg = x2; |
| 1596 | 1610 |
| 1597 if (kind_ == Code::KEYED_CALL_IC) { | 1611 if (kind_ == Code::KEYED_CALL_IC) { |
| 1598 __ Cmp(name_reg, Operand(name)); | 1612 __ Cmp(name_reg, Operand(name)); |
| 1599 __ B(ne, miss); | 1613 __ B(ne, miss); |
| (...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3239 | 3253 |
| 3240 // Miss case, call the runtime. | 3254 // Miss case, call the runtime. |
| 3241 __ Bind(&miss_force_generic); | 3255 __ Bind(&miss_force_generic); |
| 3242 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3256 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3243 } | 3257 } |
| 3244 | 3258 |
| 3245 | 3259 |
| 3246 } } // namespace v8::internal | 3260 } } // namespace v8::internal |
| 3247 | 3261 |
| 3248 #endif // V8_TARGET_ARCH_A64 | 3262 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |