Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: src/a64/stub-cache-a64.cc

Issue 155723005: A64: Synchronize with r19001. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/simulator-a64.cc ('k') | src/accessors.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 241 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
242 } 242 }
243 243
244 244
245 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 245 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
246 MacroAssembler* masm, 246 MacroAssembler* masm,
247 int index, 247 int index,
248 Register prototype, 248 Register prototype,
249 Label* miss) { 249 Label* miss) {
250 Isolate* isolate = masm->isolate(); 250 Isolate* isolate = masm->isolate();
251 // Check we're still in the same context.
252 __ Ldr(prototype, GlobalObjectMemOperand());
253 __ Cmp(prototype, Operand(isolate->global_object()));
254 __ B(ne, miss);
255 // Get the global function with the given index. 251 // Get the global function with the given index.
256 Handle<JSFunction> function( 252 Handle<JSFunction> function(
257 JSFunction::cast(isolate->native_context()->get(index))); 253 JSFunction::cast(isolate->native_context()->get(index)));
254
255 // Check we're still in the same context.
256 Register scratch = prototype;
257 __ Ldr(scratch, GlobalObjectMemOperand());
258 __ Ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
259 __ Ldr(scratch, ContextMemOperand(scratch, index));
260 __ Cmp(scratch, Operand(function));
261 __ B(ne, miss);
262
258 // Load its initial map. The global functions all have initial maps. 263 // Load its initial map. The global functions all have initial maps.
259 __ Mov(prototype, Operand(Handle<Map>(function->initial_map()))); 264 __ Mov(prototype, Operand(Handle<Map>(function->initial_map())));
260 // Load the prototype from the initial map. 265 // Load the prototype from the initial map.
261 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 266 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
262 } 267 }
263 268
264 269
265 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 270 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
266 Register dst, 271 Register dst,
267 Register src, 272 Register src,
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 746
742 static void GenerateFastApiCallBody(MacroAssembler* masm, 747 static void GenerateFastApiCallBody(MacroAssembler* masm,
743 const CallOptimization& optimization, 748 const CallOptimization& optimization,
744 int argc, 749 int argc,
745 Register holder_in, 750 Register holder_in,
746 bool restore_context) { 751 bool restore_context) {
747 ASSERT(optimization.is_simple_api_call()); 752 ASSERT(optimization.is_simple_api_call());
748 753
749 // Abi for CallApiFunctionStub. 754 // Abi for CallApiFunctionStub.
750 Register callee = x0; 755 Register callee = x0;
751 Register thunk_arg = x1; 756 Register call_data = x4;
752 Register holder = x2; 757 Register holder = x2;
753 Register api_function_address = x3; 758 Register api_function_address = x1;
754 Register call_data = x4;
755 759
756 // Put holder in place. 760 // Put holder in place.
757 __ Mov(holder, holder_in); 761 __ Mov(holder, holder_in);
758 762
759 Isolate* isolate = masm->isolate(); 763 Isolate* isolate = masm->isolate();
760 Handle<JSFunction> function = optimization.constant_function(); 764 Handle<JSFunction> function = optimization.constant_function();
761 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 765 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
762 Handle<Object> call_data_obj(api_call_info->data(), isolate); 766 Handle<Object> call_data_obj(api_call_info->data(), isolate);
763 767
764 // Put callee in place. 768 // Put callee in place.
(...skipping 12 matching lines...) Expand all
777 } 781 }
778 782
779 // Put api_function_address in place. 783 // Put api_function_address in place.
780 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 784 Address function_address = v8::ToCData<Address>(api_call_info->callback());
781 ApiFunction fun(function_address); 785 ApiFunction fun(function_address);
782 ExternalReference ref = ExternalReference(&fun, 786 ExternalReference ref = ExternalReference(&fun,
783 ExternalReference::DIRECT_API_CALL, 787 ExternalReference::DIRECT_API_CALL,
784 masm->isolate()); 788 masm->isolate());
785 __ Mov(api_function_address, Operand(ref)); 789 __ Mov(api_function_address, Operand(ref));
786 790
787 // Put thunk_arg in place.
788 __ Mov(thunk_arg, Operand(reinterpret_cast<intptr_t>(function_address)));
789
790 // Jump to stub. 791 // Jump to stub.
791 CallApiFunctionStub stub(restore_context, call_data_undefined, argc); 792 CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
792 __ TailCallStub(&stub); 793 __ TailCallStub(&stub);
793 } 794 }
794 795
795 796
796 // Generates call to API function.
797 static void GenerateFastApiCall(MacroAssembler* masm,
798 const CallOptimization& optimization,
799 int argc,
800 Handle<Map> map_to_holder,
801 CallOptimization::HolderLookup holder_lookup) {
802 Counters* counters = masm->isolate()->counters();
803 __ IncrementCounter(counters->call_const_fast_api(), 1, x0, x1);
804
805 // Move holder to a register
806 Register holder_reg = x2;
807 switch (holder_lookup) {
808 case CallOptimization::kHolderIsReceiver:
809 {
810 ASSERT(map_to_holder.is_null());
811 __ Peek(holder_reg, argc * kPointerSize);
812 }
813 break;
814 case CallOptimization::kHolderIsPrototypeOfMap:
815 {
816 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
817 if (!masm->isolate()->heap()->InNewSpace(*holder)) {
818 __ LoadObject(holder_reg, holder);
819 } else {
820 __ LoadObject(holder_reg, map_to_holder);
821 __ Ldr(holder_reg,
822 FieldMemOperand(holder_reg, Map::kPrototypeOffset));
823 }
824 }
825 break;
826 case CallOptimization::kHolderNotFound:
827 UNREACHABLE();
828 }
829 GenerateFastApiCallBody(masm,
830 optimization,
831 argc,
832 holder_reg,
833 false);
834 }
835
836
837 // Generate call to api function. 797 // Generate call to api function.
838 static void GenerateFastApiCall(MacroAssembler* masm, 798 static void GenerateFastApiCall(MacroAssembler* masm,
839 const CallOptimization& optimization, 799 const CallOptimization& optimization,
840 Register receiver, 800 Register receiver,
841 Register scratch, 801 Register scratch,
842 int argc, 802 int argc,
843 Register* values) { 803 Register* values) {
844 ASSERT(!AreAliased(receiver, scratch)); 804 ASSERT(!AreAliased(receiver, scratch));
845 805
846 __ Push(receiver); 806 __ Push(receiver);
847 // Write the arguments to stack frame. 807 // Write the arguments to stack frame.
848 for (int i = 0; i < argc; i++) { 808 for (int i = 0; i < argc; i++) {
849 // TODO(all): Groups pushes to minimize Push overhead. 809 // TODO(all): Groups pushes to minimize Push overhead.
850 Register arg = values[argc-1-i]; 810 Register arg = values[argc-1-i];
851 ASSERT(!receiver.is(arg)); 811 ASSERT(!receiver.is(arg));
852 ASSERT(!scratch.is(arg)); 812 ASSERT(!scratch.is(arg));
853 __ Push(arg); 813 __ Push(arg);
854 } 814 }
855 // Stack now matches JSFunction ABI. 815 // Stack now matches JSFunction ABI.
856 GenerateFastApiCallBody(masm, 816 GenerateFastApiCallBody(masm,
857 optimization, 817 optimization,
858 argc, 818 argc,
859 receiver, 819 receiver,
860 true); 820 true);
861 } 821 }
862 822
863 823
864 class CallInterceptorCompiler BASE_EMBEDDED {
865 public:
866 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
867 const ParameterCount& arguments,
868 Register name)
869 : stub_compiler_(stub_compiler),
870 arguments_(arguments),
871 name_(name) { }
872
873 void Compile(MacroAssembler* masm,
874 Handle<JSObject> object,
875 Handle<JSObject> holder,
876 Handle<Name> name,
877 LookupResult* lookup,
878 Register receiver,
879 Register scratch1,
880 Register scratch2,
881 Register scratch3,
882 Label* miss) {
883 ASSERT(holder->HasNamedInterceptor());
884 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
885
886 // Check that the receiver isn't a smi.
887 __ JumpIfSmi(receiver, miss);
888
889 CallOptimization optimization(lookup);
890 if (optimization.is_constant_call()) {
891 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
892 holder, lookup, name, optimization, miss);
893 } else {
894 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
895 name, holder, miss);
896 }
897 }
898
899 private:
900 void CompileCacheable(MacroAssembler* masm,
901 Handle<JSObject> object,
902 Register receiver,
903 Register scratch1,
904 Register scratch2,
905 Register scratch3,
906 Handle<JSObject> interceptor_holder,
907 LookupResult* lookup,
908 Handle<Name> name,
909 const CallOptimization& optimization,
910 Label* miss_label) {
911 ASSERT(optimization.is_constant_call());
912 ASSERT(!lookup->holder()->IsGlobalObject());
913
914 Counters* counters = masm->isolate()->counters();
915 __ IncrementCounter(counters->call_const_interceptor(), 1,
916 scratch1, scratch2);
917
918 // Check that the maps from receiver to interceptor's holder
919 // haven't changed and thus we can invoke interceptor.
920 Label miss_cleanup;
921 Register holder =
922 stub_compiler_->CheckPrototypes(
923 IC::CurrentTypeOf(object, masm->isolate()), receiver,
924 interceptor_holder, scratch1, scratch2, scratch3,
925 name, miss_label);
926
927 // Invoke an interceptor and if it provides a value,
928 // branch to |regular_invoke|.
929 Label regular_invoke;
930 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
931 &regular_invoke);
932
933 // Interceptor returned nothing for this property. Try to use cached
934 // constant function.
935
936 // Check that the maps from interceptor's holder to constant function's
937 // holder haven't changed and thus we can use cached constant function.
938 if (*interceptor_holder != lookup->holder()) {
939 stub_compiler_->CheckPrototypes(
940 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
941 handle(lookup->holder()), scratch1, scratch2, scratch3,
942 name, miss_label);
943 }
944
945 Handle<Map> lookup_map;
946 CallOptimization::HolderLookup holder_lookup =
947 CallOptimization::kHolderNotFound;
948 if (optimization.is_simple_api_call() &&
949 !lookup->holder()->IsGlobalObject()) {
950 lookup_map = optimization.LookupHolderOfExpectedType(
951 object, object, interceptor_holder, &holder_lookup);
952 if (holder_lookup == CallOptimization::kHolderNotFound) {
953 lookup_map =
954 optimization.LookupHolderOfExpectedType(
955 object,
956 interceptor_holder,
957 Handle<JSObject>(lookup->holder()),
958 &holder_lookup);
959 }
960 }
961
962 // Invoke function.
963 if (holder_lookup != CallOptimization::kHolderNotFound) {
964 int argc = arguments_.immediate();
965 GenerateFastApiCall(masm,
966 optimization,
967 argc,
968 lookup_map,
969 holder_lookup);
970 } else {
971 Handle<JSFunction> function = optimization.constant_function();
972 __ Mov(x0, receiver);
973 stub_compiler_->GenerateJumpFunction(object, function);
974 }
975
976 // Invoke a regular function.
977 __ Bind(&regular_invoke);
978 }
979
980 void CompileRegular(MacroAssembler* masm,
981 Handle<JSObject> object,
982 Register receiver,
983 Register scratch1,
984 Register scratch2,
985 Register scratch3,
986 Handle<Name> name,
987 Handle<JSObject> interceptor_holder,
988 Label* miss_label) {
989 Register holder =
990 stub_compiler_->CheckPrototypes(
991 IC::CurrentTypeOf(object, masm->isolate()), receiver,
992 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
993
994 // Call a runtime function to load the interceptor property.
995 FrameScope scope(masm, StackFrame::INTERNAL);
996 // The name_ register must be preserved across the call.
997 __ Push(name_);
998
999 CompileCallLoadPropertyWithInterceptor(
1000 masm, receiver, holder, name_, interceptor_holder,
1001 IC::kLoadPropertyWithInterceptorForCall);
1002
1003 __ Pop(name_);
1004 }
1005
1006
1007 void LoadWithInterceptor(MacroAssembler* masm,
1008 Register receiver,
1009 Register holder,
1010 Handle<JSObject> holder_obj,
1011 Register scratch,
1012 Label* interceptor_succeeded) {
1013 {
1014 FrameScope scope(masm, StackFrame::INTERNAL);
1015 __ Push(receiver, holder, name_);
1016 CompileCallLoadPropertyWithInterceptor(
1017 masm, receiver, holder, name_, holder_obj,
1018 IC::kLoadPropertyWithInterceptorOnly);
1019 // TODO(jbramley): We need two pops because holder and receiver can be
1020 // the same. In that case, we only need to preserve it once, but this is
1021 // fixed on ARM later anyway so I've left it alone for now.
1022 __ Pop(name_, holder);
1023 __ Pop(receiver);
1024 }
1025
1026 // If interceptor returns no-result sentinel, call the constant function.
1027 __ JumpIfNotRoot(x0,
1028 Heap::kNoInterceptorResultSentinelRootIndex,
1029 interceptor_succeeded);
1030 }
1031
1032 CallStubCompiler* stub_compiler_;
1033 const ParameterCount& arguments_;
1034 Register name_;
1035 };
1036
1037
1038 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { 824 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
1039 __ Jump(code, RelocInfo::CODE_TARGET); 825 __ Jump(code, RelocInfo::CODE_TARGET);
1040 } 826 }
1041 827
1042 828
1043 #undef __ 829 #undef __
1044 #define __ ACCESS_MASM(masm()) 830 #define __ ACCESS_MASM(masm())
1045 831
1046 832
1047 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, 833 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1301 __ Add(args_addr, __ StackPointer(), kPointerSize); 1087 __ Add(args_addr, __ StackPointer(), kPointerSize);
1302 1088
1303 // Stack at this point: 1089 // Stack at this point:
1304 // sp[40] callback data 1090 // sp[40] callback data
1305 // sp[32] undefined 1091 // sp[32] undefined
1306 // sp[24] undefined 1092 // sp[24] undefined
1307 // sp[16] isolate 1093 // sp[16] isolate
1308 // args_addr -> sp[8] reg 1094 // args_addr -> sp[8] reg
1309 // sp[0] name 1095 // sp[0] name
1310 1096
1311 // Pass the Handle<Name> of the property name to the runtime. 1097 // Abi for CallApiGetter.
1312 __ Mov(x0, __ StackPointer()); 1098 Register getter_address_reg = x2;
1313
1314 FrameScope frame_scope(masm(), StackFrame::MANUAL);
1315 const int kApiStackSpace = 1;
1316 __ EnterExitFrame(false, scratch4(),
1317 kApiStackSpace + MacroAssembler::kCallApiFunctionSpillSpace);
1318
1319 // Create PropertyAccessorInfo instance on the stack above the exit frame
1320 // (before the return address) with args_addr as the data.
1321 __ Poke(args_addr, 1 * kPointerSize);
1322
1323 // Get the address of ExecutableAccessorInfo instance and pass it to the
1324 // runtime.
1325 __ Add(x1, __ StackPointer(), 1 * kPointerSize);
1326
1327 // CallApiFunctionAndReturn can spill registers inside the exit frame, after
1328 // the return address and the ExecutableAccessorInfo instance.
1329 const int spill_offset = 1 + kApiStackSpace;
1330
1331 // After the call to the API function we need to free memory used for:
1332 // - the holder
1333 // - the callback data
1334 // - the isolate
1335 // - the property name
1336 // - the receiver.
1337 //
1338 // The memory allocated inside the ExitFrame will be freed when we'll leave
1339 // the ExitFrame in CallApiFunctionAndReturn.
1340 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
1341 1099
1342 // Set up the call. 1100 // Set up the call.
1343 Address getter_address = v8::ToCData<Address>(callback->getter()); 1101 Address getter_address = v8::ToCData<Address>(callback->getter());
1344 ApiFunction fun(getter_address); 1102 ApiFunction fun(getter_address);
1345 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; 1103 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1346 ExternalReference ref = ExternalReference(&fun, type, isolate()); 1104 ExternalReference ref = ExternalReference(&fun, type, isolate());
1347 Register getter_address_reg = x3;
1348 Register thunk_last_arg = x2;
1349 __ Mov(getter_address_reg, Operand(ref)); 1105 __ Mov(getter_address_reg, Operand(ref));
1350 __ Mov(thunk_last_arg, Operand(reinterpret_cast<intptr_t>(getter_address)));
1351 1106
1352 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); 1107 CallApiGetterStub stub;
1353 ExternalReference::Type thunk_type = ExternalReference::PROFILING_GETTER_CALL; 1108 __ TailCallStub(&stub);
1354 ApiFunction thunk_fun(thunk_address);
1355 ExternalReference thunk_ref =
1356 ExternalReference(&thunk_fun, thunk_type, isolate());
1357
1358 __ CallApiFunctionAndReturn(getter_address_reg,
1359 thunk_ref,
1360 thunk_last_arg,
1361 kStackUnwindSpace,
1362 spill_offset,
1363 MemOperand(fp, 6 * kPointerSize),
1364 NULL);
1365 } 1109 }
1366 1110
1367 1111
1368 void LoadStubCompiler::GenerateLoadInterceptor( 1112 void LoadStubCompiler::GenerateLoadInterceptor(
1369 Register holder_reg, 1113 Register holder_reg,
1370 Handle<Object> object, 1114 Handle<Object> object,
1371 Handle<JSObject> interceptor_holder, 1115 Handle<JSObject> interceptor_holder,
1372 LookupResult* lookup, 1116 LookupResult* lookup,
1373 Handle<Name> name) { 1117 Handle<Name> name) {
1374 ASSERT(!AreAliased(receiver(), this->name(), 1118 ASSERT(!AreAliased(receiver(), this->name(),
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1446 masm(), receiver(), holder_reg, this->name(), interceptor_holder); 1190 masm(), receiver(), holder_reg, this->name(), interceptor_holder);
1447 1191
1448 ExternalReference ref = 1192 ExternalReference ref =
1449 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1193 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1450 isolate()); 1194 isolate());
1451 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); 1195 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1452 } 1196 }
1453 } 1197 }
1454 1198
1455 1199
1456 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1457 Register name_reg = x2;
1458
1459 if (kind_ == Code::KEYED_CALL_IC) {
1460 __ Cmp(name_reg, Operand(name));
1461 __ B(ne, miss);
1462 }
1463 }
1464
1465
1466 void CallStubCompiler::GenerateFunctionCheck(Register function,
1467 Register scratch,
1468 Label* miss) {
1469 __ JumpIfSmi(function, miss);
1470 __ JumpIfNotObjectType(function, scratch, scratch, JS_FUNCTION_TYPE, miss);
1471 }
1472
1473
1474 // Load the function object into x1 register.
1475 void CallStubCompiler::GenerateLoadFunctionFromCell(
1476 Handle<Cell> cell,
1477 Handle<JSFunction> function,
1478 Label* miss) {
1479 // Get the value from the cell.
1480 __ Mov(x3, Operand(cell));
1481 Register function_reg = x1;
1482 __ Ldr(function_reg, FieldMemOperand(x3, Cell::kValueOffset));
1483
1484 // Check that the cell contains the same function.
1485 if (heap()->InNewSpace(*function)) {
1486 // We can't embed a pointer to a function in new space so we have
1487 // to verify that the shared function info is unchanged. This has
1488 // the nice side effect that multiple closures based on the same
1489 // function can all use this call IC. Before we load through the
1490 // function, we have to verify that it still is a function.
1491 GenerateFunctionCheck(function_reg, x3, miss);
1492
1493 // Check the shared function info. Make sure it hasn't changed.
1494 __ Mov(x3, Operand(Handle<SharedFunctionInfo>(function->shared())));
1495 __ Ldr(x4,
1496 FieldMemOperand(function_reg, JSFunction::kSharedFunctionInfoOffset));
1497 __ Cmp(x4, x3);
1498 } else {
1499 __ Cmp(function_reg, Operand(function));
1500 }
1501 __ B(ne, miss);
1502 }
1503
1504
1505 void CallStubCompiler::GenerateMissBranch() {
1506 Handle<Code> code =
1507 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1508 kind_,
1509 extra_state());
1510 __ Jump(code, RelocInfo::CODE_TARGET);
1511 }
1512
1513
1514 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1515 Handle<JSObject> holder,
1516 PropertyIndex index,
1517 Handle<Name> name) {
1518 Label miss;
1519 Register function = x1;
1520
1521 Register holder_reg = HandlerFrontendHeader(
1522 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1523
1524 GenerateFastPropertyLoad(masm(), function, holder_reg,
1525 index.is_inobject(holder),
1526 index.translate(holder),
1527 Representation::Tagged());
1528 GenerateJumpFunction(object, function, &miss);
1529
1530 HandlerFrontendFooter(&miss);
1531
1532 // Return the generated code.
1533 return GetCode(Code::FAST, name);
1534 }
1535
1536
1537 Handle<Code> CallStubCompiler::CompileFastApiCall(
1538 const CallOptimization& optimization,
1539 Handle<Object> object,
1540 Handle<JSObject> holder,
1541 Handle<Cell> cell,
1542 Handle<JSFunction> function,
1543 Handle<String> name) {
1544 Counters* counters = isolate()->counters();
1545
1546 ASSERT(optimization.is_simple_api_call());
1547 // Bail out if object is a global object as we don't want to
1548 // repatch it to global receiver.
1549 if (object->IsGlobalObject()) return Handle<Code>::null();
1550 if (!cell.is_null()) return Handle<Code>::null();
1551 if (!object->IsJSObject()) return Handle<Code>::null();
1552 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1553 CallOptimization::HolderLookup holder_lookup =
1554 CallOptimization::kHolderNotFound;
1555 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1556 receiver, receiver, holder, &holder_lookup);
1557 if (holder_lookup == CallOptimization::kHolderNotFound) {
1558 return Handle<Code>::null();
1559 }
1560
1561 Label miss;
1562 GenerateNameCheck(name, &miss);
1563
1564 const int argc = arguments().immediate();
1565
1566 // Get the receiver from the stack.
1567 Register receiver_reg = x1;
1568 __ Peek(receiver_reg, argc * kPointerSize);
1569
1570 // Check that the receiver isn't a smi.
1571 __ JumpIfSmi(receiver_reg, &miss);
1572
1573 __ IncrementCounter(counters->call_const(), 1, x0, x3);
1574
1575 // Check that the maps haven't changed and find a Holder as a side effect.
1576 CheckPrototypes(IC::CurrentTypeOf(object, isolate()),
1577 receiver_reg, holder, x0, x3, x4, name, &miss);
1578
1579 GenerateFastApiCall(
1580 masm(), optimization, argc, lookup_map, holder_lookup);
1581
1582 HandlerFrontendFooter(&miss);
1583
1584 // Return the generated code.
1585 return GetCode(function);
1586 }
1587
1588
1589 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1200 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1590 Label success; 1201 Label success;
1591 // Check that the object is a boolean. 1202 // Check that the object is a boolean.
1592 // TODO(all): Optimize this like LCodeGen::DoDeferredTaggedToI. 1203 // TODO(all): Optimize this like LCodeGen::DoDeferredTaggedToI.
1593 __ JumpIfRoot(object, Heap::kTrueValueRootIndex, &success); 1204 __ JumpIfRoot(object, Heap::kTrueValueRootIndex, &success);
1594 __ JumpIfNotRoot(object, Heap::kFalseValueRootIndex, miss); 1205 __ JumpIfNotRoot(object, Heap::kFalseValueRootIndex, miss);
1595 __ Bind(&success); 1206 __ Bind(&success);
1596 } 1207 }
1597 1208
1598 1209
1599 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
1600 // TODO(all): Is the use of x3 significant?
1601 if (object->IsGlobalObject()) {
1602 const int argc = arguments().immediate();
1603 const int receiver_offset = argc * kPointerSize;
1604 __ LoadRoot(x3, Heap::kUndefinedValueRootIndex);
1605 __ Poke(x3, receiver_offset);
1606 }
1607 }
1608
1609
1610 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
1611 Handle<JSObject> holder,
1612 Handle<Name> name,
1613 CheckType check,
1614 Label* miss) {
1615 // ----------- S t a t e -------------
1616 // -- x2 : name
1617 // -- lr : return address
1618 // -----------------------------------
1619 GenerateNameCheck(name, miss);
1620
1621 Register receiver = x0;
1622 Register prototype_reg = x1;
1623
1624 // Get the receiver from the stack.
1625 const int argc = arguments().immediate();
1626 const int receiver_offset = argc * kPointerSize;
1627 __ Peek(receiver, receiver_offset);
1628
1629 // Check that the receiver isn't a smi.
1630 if (check != NUMBER_CHECK) {
1631 __ JumpIfSmi(receiver, miss);
1632 }
1633
1634 // Make sure that it's okay not to patch the on stack receiver
1635 // unless we're doing a receiver map check.
1636 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
1637
1638 switch (check) {
1639 case RECEIVER_MAP_CHECK: {
1640 __ IncrementCounter(isolate()->counters()->call_const(), 1, x1, x3);
1641
1642 // Check that the maps haven't changed.
1643 receiver = CheckPrototypes(IC::CurrentTypeOf(object, isolate()),
1644 receiver, holder, x1, x3, x4, name, miss);
1645 break;
1646 }
1647 case STRING_CHECK: {
1648 // Check that the object is a string.
1649 __ JumpIfObjectType(receiver, x3, x3, FIRST_NONSTRING_TYPE, miss, ge);
1650 // Check that the maps starting from the prototype_reg haven't changed.
1651 GenerateDirectLoadGlobalFunctionPrototype(
1652 masm(), Context::STRING_FUNCTION_INDEX, prototype_reg, miss);
1653 break;
1654 }
1655 case SYMBOL_CHECK: {
1656 // Check that the object is a symbol.
1657 __ JumpIfNotObjectType(receiver, x3, x3, SYMBOL_TYPE, miss);
1658 // Check that the maps starting from the prototype_reg haven't changed.
1659 GenerateDirectLoadGlobalFunctionPrototype(
1660 masm(), Context::SYMBOL_FUNCTION_INDEX, prototype_reg, miss);
1661 break;
1662 }
1663 case NUMBER_CHECK: {
1664 Label fast;
1665 // Check that the object is a smi or a heap number.
1666 __ JumpIfSmi(receiver, &fast);
1667 __ JumpIfNotObjectType(receiver, x3, x3, HEAP_NUMBER_TYPE, miss);
1668
1669 __ Bind(&fast);
1670 // Check that the maps starting from the prototype_reg haven't changed.
1671 GenerateDirectLoadGlobalFunctionPrototype(
1672 masm(), Context::NUMBER_FUNCTION_INDEX, prototype_reg, miss);
1673 break;
1674 }
1675 case BOOLEAN_CHECK: {
1676 GenerateBooleanCheck(receiver, miss);
1677
1678 // Check that the maps starting from the prototype_reg haven't changed.
1679 GenerateDirectLoadGlobalFunctionPrototype(
1680 masm(), Context::BOOLEAN_FUNCTION_INDEX, prototype_reg, miss);
1681 break;
1682 }
1683 }
1684
1685 if (check != RECEIVER_MAP_CHECK) {
1686 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
1687 receiver = CheckPrototypes(
1688 IC::CurrentTypeOf(prototype, isolate()),
1689 prototype_reg, holder, x1, x3, x4, name, miss);
1690 }
1691
1692 return receiver;
1693 }
1694
1695
1696 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
1697 Register function,
1698 Label* miss) {
1699 ASSERT(function.Is(x1));
1700 // Check that the function really is a function.
1701 GenerateFunctionCheck(function, x3, miss);
1702 PatchImplicitReceiver(object);
1703
1704 // Invoke the function.
1705 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, NullCallWrapper());
1706 }
1707
1708
1709 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
1710 Handle<JSObject> holder,
1711 Handle<Name> name) {
1712 Label miss;
1713 Register name_reg = x2;
1714
1715 GenerateNameCheck(name, &miss);
1716
1717 const int argc = arguments().immediate();
1718 LookupResult lookup(isolate());
1719 LookupPostInterceptor(holder, name, &lookup);
1720
1721 // Get the receiver from the stack.
1722 Register receiver = x5;
1723 __ Peek(receiver, argc * kPointerSize);
1724
1725 CallInterceptorCompiler compiler(this, arguments(), name_reg);
1726 compiler.Compile(
1727 masm(), object, holder, name, &lookup, receiver, x3, x4, x0, &miss);
1728
1729 // Move returned value, the function to call, to x1 (this is required by
1730 // GenerateCallFunction).
1731 Register function = x1;
1732 __ Mov(function, x0);
1733
1734 // Restore receiver.
1735 __ Peek(receiver, argc * kPointerSize);
1736
1737 GenerateJumpFunction(object, x1, &miss);
1738
1739 HandlerFrontendFooter(&miss);
1740
1741 // Return the generated code.
1742 return GetCode(Code::FAST, name);
1743 }
1744
1745
1746 Handle<Code> CallStubCompiler::CompileCallGlobal(
1747 Handle<JSObject> object,
1748 Handle<GlobalObject> holder,
1749 Handle<PropertyCell> cell,
1750 Handle<JSFunction> function,
1751 Handle<Name> name) {
1752 if (HasCustomCallGenerator(function)) {
1753 Handle<Code> code = CompileCustomCall(
1754 object, holder, cell, function, Handle<String>::cast(name),
1755 Code::NORMAL);
1756 // A null handle means bail out to the regular compiler code below.
1757 if (!code.is_null()) return code;
1758 }
1759
1760 Label miss;
1761 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1762 // Potentially loads a closure that matches the shared function info of the
1763 // function, rather than function.
1764 GenerateLoadFunctionFromCell(cell, function, &miss);
1765 // After these two calls the receiver is left in x0 and the function in x1.
1766 Register function_reg = x1;
1767
1768 Counters* counters = isolate()->counters();
1769 __ IncrementCounter(counters->call_global_inline(), 1, x3, x4);
1770 GenerateJumpFunction(object, function_reg, function);
1771 HandlerFrontendFooter(&miss);
1772
1773 // Return the generated code.
1774 return GetCode(Code::NORMAL, name);
1775 }
1776
1777
1778 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1210 Handle<Code> StoreStubCompiler::CompileStoreCallback(
1779 Handle<JSObject> object, 1211 Handle<JSObject> object,
1780 Handle<JSObject> holder, 1212 Handle<JSObject> holder,
1781 Handle<Name> name, 1213 Handle<Name> name,
1782 Handle<ExecutableAccessorInfo> callback) { 1214 Handle<ExecutableAccessorInfo> callback) {
1783 ASM_LOCATION("StoreStubCompiler::CompileStoreCallback"); 1215 ASM_LOCATION("StoreStubCompiler::CompileStoreCallback");
1784 Register holder_reg = HandlerFrontend( 1216 Register holder_reg = HandlerFrontend(
1785 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); 1217 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
1786 1218
1787 // Stub never generated for non-global objects that require access checks. 1219 // Stub never generated for non-global objects that require access checks.
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 #define __ ACCESS_MASM(masm()) 1403 #define __ ACCESS_MASM(masm())
1972 1404
1973 1405
1974 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 1406 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
1975 Handle<HeapType> type, 1407 Handle<HeapType> type,
1976 Handle<GlobalObject> global, 1408 Handle<GlobalObject> global,
1977 Handle<PropertyCell> cell, 1409 Handle<PropertyCell> cell,
1978 Handle<Name> name, 1410 Handle<Name> name,
1979 bool is_dont_delete) { 1411 bool is_dont_delete) {
1980 Label miss; 1412 Label miss;
1981
1982 HandlerFrontendHeader(type, receiver(), global, name, &miss); 1413 HandlerFrontendHeader(type, receiver(), global, name, &miss);
1983 1414
1984 // Get the value from the cell. 1415 // Get the value from the cell.
1985 __ Mov(x3, Operand(cell)); 1416 __ Mov(x3, Operand(cell));
1986 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); 1417 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset));
1987 1418
1988 // Check for deleted property if property can actually be deleted. 1419 // Check for deleted property if property can actually be deleted.
1989 if (!is_dont_delete) { 1420 if (!is_dont_delete) {
1990 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); 1421 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss);
1991 } 1422 }
1992 1423
1993 HandlerFrontendFooter(name, &miss);
1994
1995 Counters* counters = isolate()->counters(); 1424 Counters* counters = isolate()->counters();
1996 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); 1425 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3);
1997 __ Mov(x0, x4); 1426 __ Mov(x0, x4);
1998 __ Ret(); 1427 __ Ret();
1999 1428
1429 HandlerFrontendFooter(name, &miss);
1430
2000 // Return the generated code. 1431 // Return the generated code.
2001 return GetCode(kind(), Code::NORMAL, name); 1432 return GetCode(kind(), Code::NORMAL, name);
2002 } 1433 }
2003 1434
2004 1435
2005 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 1436 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2006 TypeHandleList* types, 1437 TypeHandleList* types,
2007 CodeHandleList* handlers, 1438 CodeHandleList* handlers,
2008 Handle<Name> name, 1439 Handle<Name> name,
2009 Code::StubType type, 1440 Code::StubType type,
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2130 1561
2131 // Miss case, call the runtime. 1562 // Miss case, call the runtime.
2132 __ Bind(&miss); 1563 __ Bind(&miss);
2133 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 1564 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2134 } 1565 }
2135 1566
2136 1567
2137 } } // namespace v8::internal 1568 } } // namespace v8::internal
2138 1569
2139 #endif // V8_TARGET_ARCH_A64 1570 #endif // V8_TARGET_ARCH_A64
OLDNEW
« no previous file with comments | « src/a64/simulator-a64.cc ('k') | src/accessors.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698