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

Side by Side Diff: src/arm/stub-cache-arm.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/arm/simulator-arm.cc ('k') | src/array.js » ('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 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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 288 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
289 } 289 }
290 290
291 291
292 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 292 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
293 MacroAssembler* masm, 293 MacroAssembler* masm,
294 int index, 294 int index,
295 Register prototype, 295 Register prototype,
296 Label* miss) { 296 Label* miss) {
297 Isolate* isolate = masm->isolate(); 297 Isolate* isolate = masm->isolate();
298 // Check we're still in the same context.
299 __ ldr(prototype,
300 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
301 __ Move(ip, isolate->global_object());
302 __ cmp(prototype, ip);
303 __ b(ne, miss);
304 // Get the global function with the given index. 298 // Get the global function with the given index.
305 Handle<JSFunction> function( 299 Handle<JSFunction> function(
306 JSFunction::cast(isolate->native_context()->get(index))); 300 JSFunction::cast(isolate->native_context()->get(index)));
301
302 // Check we're still in the same context.
303 Register scratch = prototype;
304 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
305 __ ldr(scratch, MemOperand(cp, offset));
306 __ ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
307 __ ldr(scratch, MemOperand(scratch, Context::SlotOffset(index)));
308 __ Move(ip, function);
309 __ cmp(ip, scratch);
310 __ b(ne, miss);
311
307 // Load its initial map. The global functions all have initial maps. 312 // Load its initial map. The global functions all have initial maps.
308 __ Move(prototype, Handle<Map>(function->initial_map())); 313 __ Move(prototype, Handle<Map>(function->initial_map()));
309 // Load the prototype from the initial map. 314 // Load the prototype from the initial map.
310 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 315 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
311 } 316 }
312 317
313 318
314 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 319 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
315 Register dst, 320 Register dst,
316 Register src, 321 Register src,
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 const CallOptimization& optimization, 786 const CallOptimization& optimization,
782 int argc, 787 int argc,
783 Register holder_in, 788 Register holder_in,
784 bool restore_context) { 789 bool restore_context) {
785 ASSERT(optimization.is_simple_api_call()); 790 ASSERT(optimization.is_simple_api_call());
786 791
787 // Abi for CallApiFunctionStub. 792 // Abi for CallApiFunctionStub.
788 Register callee = r0; 793 Register callee = r0;
789 Register call_data = r4; 794 Register call_data = r4;
790 Register holder = r2; 795 Register holder = r2;
791 Register api_function_address = r3; 796 Register api_function_address = r1;
792 Register thunk_arg = r1;
793 797
794 // Put holder in place. 798 // Put holder in place.
795 __ Move(holder, holder_in); 799 __ Move(holder, holder_in);
796 800
797 Isolate* isolate = masm->isolate(); 801 Isolate* isolate = masm->isolate();
798 Handle<JSFunction> function = optimization.constant_function(); 802 Handle<JSFunction> function = optimization.constant_function();
799 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 803 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
800 Handle<Object> call_data_obj(api_call_info->data(), isolate); 804 Handle<Object> call_data_obj(api_call_info->data(), isolate);
801 805
802 // Put callee in place. 806 // Put callee in place.
(...skipping 12 matching lines...) Expand all
815 } 819 }
816 820
817 // Put api_function_address in place. 821 // Put api_function_address in place.
818 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 822 Address function_address = v8::ToCData<Address>(api_call_info->callback());
819 ApiFunction fun(function_address); 823 ApiFunction fun(function_address);
820 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; 824 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
821 ExternalReference ref = ExternalReference(&fun, 825 ExternalReference ref = ExternalReference(&fun,
822 type, 826 type,
823 masm->isolate()); 827 masm->isolate());
824 __ mov(api_function_address, Operand(ref)); 828 __ mov(api_function_address, Operand(ref));
825 __ mov(thunk_arg, Operand(reinterpret_cast<int32_t>(function_address)));
826 829
827 // Jump to stub. 830 // Jump to stub.
828 CallApiFunctionStub stub(restore_context, call_data_undefined, argc); 831 CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
829 __ TailCallStub(&stub); 832 __ TailCallStub(&stub);
830 } 833 }
831 834
832 835
833 // Generates call to API function.
834 static void GenerateFastApiCall(MacroAssembler* masm,
835 const CallOptimization& optimization,
836 int argc,
837 Handle<Map> map_to_holder,
838 CallOptimization::HolderLookup holder_lookup) {
839 Counters* counters = masm->isolate()->counters();
840 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r1);
841
842 // Move holder to a register
843 Register holder_reg = r2;
844 switch (holder_lookup) {
845 case CallOptimization::kHolderIsReceiver:
846 {
847 ASSERT(map_to_holder.is_null());
848 __ ldr(holder_reg, MemOperand(sp, argc * kPointerSize));
849 }
850 break;
851 case CallOptimization::kHolderIsPrototypeOfMap:
852 {
853 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
854 if (!masm->isolate()->heap()->InNewSpace(*holder)) {
855 __ Move(holder_reg, holder);
856 } else {
857 __ Move(holder_reg, map_to_holder);
858 __ ldr(holder_reg,
859 FieldMemOperand(holder_reg, Map::kPrototypeOffset));
860 }
861 }
862 break;
863 case CallOptimization::kHolderNotFound:
864 UNREACHABLE();
865 }
866 GenerateFastApiCallBody(masm,
867 optimization,
868 argc,
869 holder_reg,
870 false);
871 }
872
873
874 // Generate call to api function. 836 // Generate call to api function.
875 static void GenerateFastApiCall(MacroAssembler* masm, 837 static void GenerateFastApiCall(MacroAssembler* masm,
876 const CallOptimization& optimization, 838 const CallOptimization& optimization,
877 Register receiver, 839 Register receiver,
878 Register scratch, 840 Register scratch,
879 int argc, 841 int argc,
880 Register* values) { 842 Register* values) {
881 ASSERT(!receiver.is(scratch)); 843 ASSERT(!receiver.is(scratch));
882 __ push(receiver); 844 __ push(receiver);
883 // Write the arguments to stack frame. 845 // Write the arguments to stack frame.
884 for (int i = 0; i < argc; i++) { 846 for (int i = 0; i < argc; i++) {
885 Register arg = values[argc-1-i]; 847 Register arg = values[argc-1-i];
886 ASSERT(!receiver.is(arg)); 848 ASSERT(!receiver.is(arg));
887 ASSERT(!scratch.is(arg)); 849 ASSERT(!scratch.is(arg));
888 __ push(arg); 850 __ push(arg);
889 } 851 }
890 // Stack now matches JSFunction abi. 852 // Stack now matches JSFunction abi.
891 GenerateFastApiCallBody(masm, 853 GenerateFastApiCallBody(masm,
892 optimization, 854 optimization,
893 argc, 855 argc,
894 receiver, 856 receiver,
895 true); 857 true);
896 } 858 }
897 859
898 860
899 class CallInterceptorCompiler BASE_EMBEDDED {
900 public:
901 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
902 const ParameterCount& arguments,
903 Register name)
904 : stub_compiler_(stub_compiler),
905 arguments_(arguments),
906 name_(name) {}
907
908 void Compile(MacroAssembler* masm,
909 Handle<JSObject> object,
910 Handle<JSObject> holder,
911 Handle<Name> name,
912 LookupResult* lookup,
913 Register receiver,
914 Register scratch1,
915 Register scratch2,
916 Register scratch3,
917 Label* miss) {
918 ASSERT(holder->HasNamedInterceptor());
919 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
920
921 // Check that the receiver isn't a smi.
922 __ JumpIfSmi(receiver, miss);
923 CallOptimization optimization(lookup);
924 if (optimization.is_constant_call()) {
925 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
926 holder, lookup, name, optimization, miss);
927 } else {
928 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
929 name, holder, miss);
930 }
931 }
932
933 private:
934 void CompileCacheable(MacroAssembler* masm,
935 Handle<JSObject> object,
936 Register receiver,
937 Register scratch1,
938 Register scratch2,
939 Register scratch3,
940 Handle<JSObject> interceptor_holder,
941 LookupResult* lookup,
942 Handle<Name> name,
943 const CallOptimization& optimization,
944 Label* miss_label) {
945 ASSERT(optimization.is_constant_call());
946 ASSERT(!lookup->holder()->IsGlobalObject());
947 Counters* counters = masm->isolate()->counters();
948 __ IncrementCounter(counters->call_const_interceptor(), 1,
949 scratch1, scratch2);
950
951 // Check that the maps from receiver to interceptor's holder
952 // haven't changed and thus we can invoke interceptor.
953 Label miss_cleanup;
954 Register holder =
955 stub_compiler_->CheckPrototypes(
956 IC::CurrentTypeOf(object, masm->isolate()), receiver,
957 interceptor_holder, scratch1, scratch2, scratch3,
958 name, miss_label);
959
960 // Invoke an interceptor and if it provides a value,
961 // branch to |regular_invoke|.
962 Label regular_invoke;
963 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
964 &regular_invoke);
965
966 // Interceptor returned nothing for this property. Try to use cached
967 // constant function.
968
969 // Check that the maps from interceptor's holder to constant function's
970 // holder haven't changed and thus we can use cached constant function.
971 if (*interceptor_holder != lookup->holder()) {
972 stub_compiler_->CheckPrototypes(
973 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
974 handle(lookup->holder()), scratch1, scratch2, scratch3,
975 name, miss_label);
976 }
977
978 Handle<Map> lookup_map;
979 CallOptimization::HolderLookup holder_lookup =
980 CallOptimization::kHolderNotFound;
981 if (optimization.is_simple_api_call() &&
982 !lookup->holder()->IsGlobalObject()) {
983 lookup_map = optimization.LookupHolderOfExpectedType(
984 object, object, interceptor_holder, &holder_lookup);
985 if (holder_lookup == CallOptimization::kHolderNotFound) {
986 lookup_map =
987 optimization.LookupHolderOfExpectedType(
988 object,
989 interceptor_holder,
990 Handle<JSObject>(lookup->holder()),
991 &holder_lookup);
992 }
993 }
994
995 // Invoke function.
996 if (holder_lookup != CallOptimization::kHolderNotFound) {
997 int argc = arguments_.immediate();
998 GenerateFastApiCall(masm,
999 optimization,
1000 argc,
1001 lookup_map,
1002 holder_lookup);
1003 } else {
1004 Handle<JSFunction> function = optimization.constant_function();
1005 __ Move(r0, receiver);
1006 stub_compiler_->GenerateJumpFunction(object, function);
1007 }
1008
1009 // Invoke a regular function.
1010 __ bind(&regular_invoke);
1011 }
1012
1013 void CompileRegular(MacroAssembler* masm,
1014 Handle<JSObject> object,
1015 Register receiver,
1016 Register scratch1,
1017 Register scratch2,
1018 Register scratch3,
1019 Handle<Name> name,
1020 Handle<JSObject> interceptor_holder,
1021 Label* miss_label) {
1022 Register holder =
1023 stub_compiler_->CheckPrototypes(
1024 IC::CurrentTypeOf(object, masm->isolate()), receiver,
1025 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
1026
1027 // Call a runtime function to load the interceptor property.
1028 FrameScope scope(masm, StackFrame::INTERNAL);
1029 // Save the name_ register across the call.
1030 __ push(name_);
1031
1032 CompileCallLoadPropertyWithInterceptor(
1033 masm, receiver, holder, name_, interceptor_holder,
1034 IC::kLoadPropertyWithInterceptorForCall);
1035
1036 // Restore the name_ register.
1037 __ pop(name_);
1038 // Leave the internal frame.
1039 }
1040
1041 void LoadWithInterceptor(MacroAssembler* masm,
1042 Register receiver,
1043 Register holder,
1044 Handle<JSObject> holder_obj,
1045 Register scratch,
1046 Label* interceptor_succeeded) {
1047 {
1048 FrameScope scope(masm, StackFrame::INTERNAL);
1049 __ Push(receiver);
1050 __ Push(holder, name_);
1051 CompileCallLoadPropertyWithInterceptor(
1052 masm, receiver, holder, name_, holder_obj,
1053 IC::kLoadPropertyWithInterceptorOnly);
1054 __ pop(name_);
1055 __ pop(holder);
1056 __ pop(receiver);
1057 }
1058 // If interceptor returns no-result sentinel, call the constant function.
1059 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
1060 __ cmp(r0, scratch);
1061 __ b(ne, interceptor_succeeded);
1062 }
1063
1064 CallStubCompiler* stub_compiler_;
1065 const ParameterCount& arguments_;
1066 Register name_;
1067 };
1068
1069
1070 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { 861 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
1071 __ Jump(code, RelocInfo::CODE_TARGET); 862 __ Jump(code, RelocInfo::CODE_TARGET);
1072 } 863 }
1073 864
1074 865
1075 #undef __ 866 #undef __
1076 #define __ ACCESS_MASM(masm()) 867 #define __ ACCESS_MASM(masm())
1077 868
1078 869
1079 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, 870 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 } 1106 }
1316 __ push(scratch3()); 1107 __ push(scratch3());
1317 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); 1108 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex);
1318 __ mov(scratch4(), scratch3()); 1109 __ mov(scratch4(), scratch3());
1319 __ Push(scratch3(), scratch4()); 1110 __ Push(scratch3(), scratch4());
1320 __ mov(scratch4(), 1111 __ mov(scratch4(),
1321 Operand(ExternalReference::isolate_address(isolate()))); 1112 Operand(ExternalReference::isolate_address(isolate())));
1322 __ Push(scratch4(), reg); 1113 __ Push(scratch4(), reg);
1323 __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_ 1114 __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_
1324 __ push(name()); 1115 __ push(name());
1325 __ mov(r0, sp); // r0 = Handle<Name>
1326 1116
1327 const int kApiStackSpace = 1; 1117 // Abi for CallApiGetter
1328 FrameScope frame_scope(masm(), StackFrame::MANUAL); 1118 Register getter_address_reg = r2;
1329 __ EnterExitFrame(false, kApiStackSpace);
1330 1119
1331 // Create PropertyAccessorInfo instance on the stack above the exit frame with
1332 // scratch2 (internal::Object** args_) as the data.
1333 __ str(scratch2(), MemOperand(sp, 1 * kPointerSize));
1334 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo&
1335
1336 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
1337 Address getter_address = v8::ToCData<Address>(callback->getter()); 1120 Address getter_address = v8::ToCData<Address>(callback->getter());
1338
1339 ApiFunction fun(getter_address); 1121 ApiFunction fun(getter_address);
1340 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; 1122 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1341 ExternalReference ref = ExternalReference(&fun, type, isolate()); 1123 ExternalReference ref = ExternalReference(&fun, type, isolate());
1342 Register getter_address_reg = r3;
1343 Register thunk_last_arg = r2;
1344 __ mov(getter_address_reg, Operand(ref)); 1124 __ mov(getter_address_reg, Operand(ref));
1345 __ mov(thunk_last_arg, Operand(reinterpret_cast<int32_t>(getter_address)));
1346 1125
1347 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); 1126 CallApiGetterStub stub;
1348 ExternalReference::Type thunk_type = 1127 __ TailCallStub(&stub);
1349 ExternalReference::PROFILING_GETTER_CALL;
1350 ApiFunction thunk_fun(thunk_address);
1351 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
1352 isolate());
1353 __ CallApiFunctionAndReturn(getter_address_reg,
1354 thunk_ref,
1355 thunk_last_arg,
1356 kStackUnwindSpace,
1357 MemOperand(fp, 6 * kPointerSize),
1358 NULL);
1359 } 1128 }
1360 1129
1361 1130
1362 void LoadStubCompiler::GenerateLoadInterceptor( 1131 void LoadStubCompiler::GenerateLoadInterceptor(
1363 Register holder_reg, 1132 Register holder_reg,
1364 Handle<Object> object, 1133 Handle<Object> object,
1365 Handle<JSObject> interceptor_holder, 1134 Handle<JSObject> interceptor_holder,
1366 LookupResult* lookup, 1135 LookupResult* lookup,
1367 Handle<Name> name) { 1136 Handle<Name> name) {
1368 ASSERT(interceptor_holder->HasNamedInterceptor()); 1137 ASSERT(interceptor_holder->HasNamedInterceptor());
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1440 this->name(), interceptor_holder); 1209 this->name(), interceptor_holder);
1441 1210
1442 ExternalReference ref = 1211 ExternalReference ref =
1443 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1212 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1444 isolate()); 1213 isolate());
1445 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); 1214 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1446 } 1215 }
1447 } 1216 }
1448 1217
1449 1218
1450 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1451 if (kind_ == Code::KEYED_CALL_IC) {
1452 __ cmp(r2, Operand(name));
1453 __ b(ne, miss);
1454 }
1455 }
1456
1457
1458 void CallStubCompiler::GenerateFunctionCheck(Register function,
1459 Register scratch,
1460 Label* miss) {
1461 __ JumpIfSmi(function, miss);
1462 __ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE);
1463 __ b(ne, miss);
1464 }
1465
1466
1467 void CallStubCompiler::GenerateLoadFunctionFromCell(
1468 Handle<Cell> cell,
1469 Handle<JSFunction> function,
1470 Label* miss) {
1471 // Get the value from the cell.
1472 __ mov(r3, Operand(cell));
1473 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset));
1474
1475 // Check that the cell contains the same function.
1476 if (heap()->InNewSpace(*function)) {
1477 // We can't embed a pointer to a function in new space so we have
1478 // to verify that the shared function info is unchanged. This has
1479 // the nice side effect that multiple closures based on the same
1480 // function can all use this call IC. Before we load through the
1481 // function, we have to verify that it still is a function.
1482 GenerateFunctionCheck(r1, r3, miss);
1483
1484 // Check the shared function info. Make sure it hasn't changed.
1485 __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
1486 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1487 __ cmp(r4, r3);
1488 } else {
1489 __ cmp(r1, Operand(function));
1490 }
1491 __ b(ne, miss);
1492 }
1493
1494
1495 void CallStubCompiler::GenerateMissBranch() {
1496 Handle<Code> code =
1497 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1498 kind_,
1499 extra_state());
1500 __ Jump(code, RelocInfo::CODE_TARGET);
1501 }
1502
1503
1504 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1505 Handle<JSObject> holder,
1506 PropertyIndex index,
1507 Handle<Name> name) {
1508 Label miss;
1509
1510 Register reg = HandlerFrontendHeader(
1511 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1512 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
1513 index.translate(holder), Representation::Tagged());
1514 GenerateJumpFunction(object, r1, &miss);
1515
1516 HandlerFrontendFooter(&miss);
1517
1518 // Return the generated code.
1519 return GetCode(Code::FAST, name);
1520 }
1521
1522
1523 Handle<Code> CallStubCompiler::CompileFastApiCall(
1524 const CallOptimization& optimization,
1525 Handle<Object> object,
1526 Handle<JSObject> holder,
1527 Handle<Cell> cell,
1528 Handle<JSFunction> function,
1529 Handle<String> name) {
1530 Counters* counters = isolate()->counters();
1531
1532 ASSERT(optimization.is_simple_api_call());
1533 // Bail out if object is a global object as we don't want to
1534 // repatch it to global receiver.
1535 if (object->IsGlobalObject()) return Handle<Code>::null();
1536 if (!cell.is_null()) return Handle<Code>::null();
1537 if (!object->IsJSObject()) return Handle<Code>::null();
1538 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1539 CallOptimization::HolderLookup holder_lookup =
1540 CallOptimization::kHolderNotFound;
1541 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1542 receiver, receiver, holder, &holder_lookup);
1543 if (holder_lookup == CallOptimization::kHolderNotFound) {
1544 return Handle<Code>::null();
1545 }
1546
1547 Label miss;
1548 GenerateNameCheck(name, &miss);
1549
1550 // Get the receiver from the stack.
1551 const int argc = arguments().immediate();
1552 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
1553
1554 // Check that the receiver isn't a smi.
1555 __ JumpIfSmi(r1, &miss);
1556
1557 __ IncrementCounter(counters->call_const(), 1, r0, r3);
1558
1559 // Check that the maps haven't changed and find a Holder as a side effect.
1560 CheckPrototypes(
1561 IC::CurrentTypeOf(object, isolate()),
1562 r1, holder, r0, r3, r4, name, &miss);
1563
1564 GenerateFastApiCall(
1565 masm(), optimization, argc, lookup_map, holder_lookup);
1566
1567 HandlerFrontendFooter(&miss);
1568
1569 // Return the generated code.
1570 return GetCode(function);
1571 }
1572
1573
1574 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1219 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1575 Label success; 1220 Label success;
1576 // Check that the object is a boolean. 1221 // Check that the object is a boolean.
1577 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1222 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1578 __ cmp(object, ip); 1223 __ cmp(object, ip);
1579 __ b(eq, &success); 1224 __ b(eq, &success);
1580 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 1225 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1581 __ cmp(object, ip); 1226 __ cmp(object, ip);
1582 __ b(ne, miss); 1227 __ b(ne, miss);
1583 __ bind(&success); 1228 __ bind(&success);
1584 } 1229 }
1585 1230
1586 1231
1587 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
1588 if (object->IsGlobalObject()) {
1589 const int argc = arguments().immediate();
1590 const int receiver_offset = argc * kPointerSize;
1591 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
1592 __ str(r3, MemOperand(sp, receiver_offset));
1593 }
1594 }
1595
1596
1597 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
1598 Handle<JSObject> holder,
1599 Handle<Name> name,
1600 CheckType check,
1601 Label* miss) {
1602 // ----------- S t a t e -------------
1603 // -- r2 : name
1604 // -- lr : return address
1605 // -----------------------------------
1606 GenerateNameCheck(name, miss);
1607
1608 Register reg = r0;
1609
1610 // Get the receiver from the stack
1611 const int argc = arguments().immediate();
1612 const int receiver_offset = argc * kPointerSize;
1613 __ ldr(r0, MemOperand(sp, receiver_offset));
1614
1615 // Check that the receiver isn't a smi.
1616 if (check != NUMBER_CHECK) {
1617 __ JumpIfSmi(r0, miss);
1618 }
1619
1620 // Make sure that it's okay not to patch the on stack receiver
1621 // unless we're doing a receiver map check.
1622 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
1623 switch (check) {
1624 case RECEIVER_MAP_CHECK:
1625 __ IncrementCounter(isolate()->counters()->call_const(), 1, r1, r3);
1626
1627 // Check that the maps haven't changed.
1628 reg = CheckPrototypes(
1629 IC::CurrentTypeOf(object, isolate()),
1630 reg, holder, r1, r3, r4, name, miss);
1631 break;
1632
1633 case STRING_CHECK: {
1634 // Check that the object is a string.
1635 __ CompareObjectType(reg, r3, r3, FIRST_NONSTRING_TYPE);
1636 __ b(ge, miss);
1637 // Check that the maps starting from the prototype haven't changed.
1638 GenerateDirectLoadGlobalFunctionPrototype(
1639 masm(), Context::STRING_FUNCTION_INDEX, r1, miss);
1640 break;
1641 }
1642 case SYMBOL_CHECK: {
1643 // Check that the object is a symbol.
1644 __ CompareObjectType(reg, r3, r3, SYMBOL_TYPE);
1645 __ b(ne, miss);
1646 // Check that the maps starting from the prototype haven't changed.
1647 GenerateDirectLoadGlobalFunctionPrototype(
1648 masm(), Context::SYMBOL_FUNCTION_INDEX, r1, miss);
1649 break;
1650 }
1651 case NUMBER_CHECK: {
1652 Label fast;
1653 // Check that the object is a smi or a heap number.
1654 __ JumpIfSmi(reg, &fast);
1655 __ CompareObjectType(reg, r3, r3, HEAP_NUMBER_TYPE);
1656 __ b(ne, miss);
1657 __ bind(&fast);
1658 // Check that the maps starting from the prototype haven't changed.
1659 GenerateDirectLoadGlobalFunctionPrototype(
1660 masm(), Context::NUMBER_FUNCTION_INDEX, r1, miss);
1661 break;
1662 }
1663 case BOOLEAN_CHECK: {
1664 GenerateBooleanCheck(reg, miss);
1665
1666 // Check that the maps starting from the prototype haven't changed.
1667 GenerateDirectLoadGlobalFunctionPrototype(
1668 masm(), Context::BOOLEAN_FUNCTION_INDEX, r1, miss);
1669 break;
1670 }
1671 }
1672
1673 if (check != RECEIVER_MAP_CHECK) {
1674 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
1675 reg = CheckPrototypes(
1676 IC::CurrentTypeOf(prototype, isolate()),
1677 r1, holder, r1, r3, r4, name, miss);
1678 }
1679
1680 return reg;
1681 }
1682
1683
1684 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
1685 Register function,
1686 Label* miss) {
1687 ASSERT(function.is(r1));
1688 // Check that the function really is a function.
1689 GenerateFunctionCheck(function, r3, miss);
1690 PatchImplicitReceiver(object);
1691
1692 // Invoke the function.
1693 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, NullCallWrapper());
1694 }
1695
1696
1697 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
1698 Handle<JSObject> holder,
1699 Handle<Name> name) {
1700 Label miss;
1701 GenerateNameCheck(name, &miss);
1702
1703 // Get the number of arguments.
1704 const int argc = arguments().immediate();
1705 LookupResult lookup(isolate());
1706 LookupPostInterceptor(holder, name, &lookup);
1707
1708 // Get the receiver from the stack.
1709 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
1710
1711 CallInterceptorCompiler compiler(this, arguments(), r2);
1712 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0,
1713 &miss);
1714
1715 // Move returned value, the function to call, to r1.
1716 __ mov(r1, r0);
1717 // Restore receiver.
1718 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1719
1720 GenerateJumpFunction(object, r1, &miss);
1721
1722 HandlerFrontendFooter(&miss);
1723
1724 // Return the generated code.
1725 return GetCode(Code::FAST, name);
1726 }
1727
1728
1729 Handle<Code> CallStubCompiler::CompileCallGlobal(
1730 Handle<JSObject> object,
1731 Handle<GlobalObject> holder,
1732 Handle<PropertyCell> cell,
1733 Handle<JSFunction> function,
1734 Handle<Name> name) {
1735 if (HasCustomCallGenerator(function)) {
1736 Handle<Code> code = CompileCustomCall(
1737 object, holder, cell, function, Handle<String>::cast(name),
1738 Code::NORMAL);
1739 // A null handle means bail out to the regular compiler code below.
1740 if (!code.is_null()) return code;
1741 }
1742
1743 Label miss;
1744 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1745 // Potentially loads a closure that matches the shared function info of the
1746 // function, rather than function.
1747 GenerateLoadFunctionFromCell(cell, function, &miss);
1748
1749 Counters* counters = isolate()->counters();
1750 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
1751 GenerateJumpFunction(object, r1, function);
1752 HandlerFrontendFooter(&miss);
1753
1754 // Return the generated code.
1755 return GetCode(Code::NORMAL, name);
1756 }
1757
1758
1759 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1232 Handle<Code> StoreStubCompiler::CompileStoreCallback(
1760 Handle<JSObject> object, 1233 Handle<JSObject> object,
1761 Handle<JSObject> holder, 1234 Handle<JSObject> holder,
1762 Handle<Name> name, 1235 Handle<Name> name,
1763 Handle<ExecutableAccessorInfo> callback) { 1236 Handle<ExecutableAccessorInfo> callback) {
1764 Register holder_reg = HandlerFrontend( 1237 Register holder_reg = HandlerFrontend(
1765 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); 1238 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
1766 1239
1767 // Stub never generated for non-global objects that require access checks. 1240 // Stub never generated for non-global objects that require access checks.
1768 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 1241 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1963 #define __ ACCESS_MASM(masm()) 1436 #define __ ACCESS_MASM(masm())
1964 1437
1965 1438
1966 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 1439 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
1967 Handle<HeapType> type, 1440 Handle<HeapType> type,
1968 Handle<GlobalObject> global, 1441 Handle<GlobalObject> global,
1969 Handle<PropertyCell> cell, 1442 Handle<PropertyCell> cell,
1970 Handle<Name> name, 1443 Handle<Name> name,
1971 bool is_dont_delete) { 1444 bool is_dont_delete) {
1972 Label miss; 1445 Label miss;
1973
1974 HandlerFrontendHeader(type, receiver(), global, name, &miss); 1446 HandlerFrontendHeader(type, receiver(), global, name, &miss);
1975 1447
1976 // Get the value from the cell. 1448 // Get the value from the cell.
1977 __ mov(r3, Operand(cell)); 1449 __ mov(r3, Operand(cell));
1978 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); 1450 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset));
1979 1451
1980 // Check for deleted property if property can actually be deleted. 1452 // Check for deleted property if property can actually be deleted.
1981 if (!is_dont_delete) { 1453 if (!is_dont_delete) {
1982 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1454 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1983 __ cmp(r4, ip); 1455 __ cmp(r4, ip);
1984 __ b(eq, &miss); 1456 __ b(eq, &miss);
1985 } 1457 }
1986 1458
1987 HandlerFrontendFooter(name, &miss);
1988
1989 Counters* counters = isolate()->counters(); 1459 Counters* counters = isolate()->counters();
1990 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); 1460 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
1991 __ mov(r0, r4); 1461 __ mov(r0, r4);
1992 __ Ret(); 1462 __ Ret();
1993 1463
1464 HandlerFrontendFooter(name, &miss);
1465
1994 // Return the generated code. 1466 // Return the generated code.
1995 return GetCode(kind(), Code::NORMAL, name); 1467 return GetCode(kind(), Code::NORMAL, name);
1996 } 1468 }
1997 1469
1998 1470
1999 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 1471 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2000 TypeHandleList* types, 1472 TypeHandleList* types,
2001 CodeHandleList* handlers, 1473 CodeHandleList* handlers,
2002 Handle<Name> name, 1474 Handle<Name> name,
2003 Code::StubType type, 1475 Code::StubType type,
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
2120 // ----------------------------------- 1592 // -----------------------------------
2121 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 1593 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2122 } 1594 }
2123 1595
2124 1596
2125 #undef __ 1597 #undef __
2126 1598
2127 } } // namespace v8::internal 1599 } } // namespace v8::internal
2128 1600
2129 #endif // V8_TARGET_ARCH_ARM 1601 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.cc ('k') | src/array.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698