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

Side by Side Diff: src/arm/builtins-arm.cc

Issue 660095: Merge revision 3813 to 3930 from bleeding_edge to partial snapshots branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: '' Created 10 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/assembler-thumb2-inl.h ('k') | src/arm/codegen-arm.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 __ b(ne, &non_function_call); 492 __ b(ne, &non_function_call);
493 493
494 // Jump to the function-specific construct stub. 494 // Jump to the function-specific construct stub.
495 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 495 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
496 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); 496 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset));
497 __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); 497 __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
498 498
499 // r0: number of arguments 499 // r0: number of arguments
500 // r1: called object 500 // r1: called object
501 __ bind(&non_function_call); 501 __ bind(&non_function_call);
502 502 // CALL_NON_FUNCTION expects the non-function constructor as receiver
503 // (instead of the original receiver from the call site). The receiver is
504 // stack element argc.
505 __ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
503 // Set expected number of arguments to zero (not changing r0). 506 // Set expected number of arguments to zero (not changing r0).
504 __ mov(r2, Operand(0)); 507 __ mov(r2, Operand(0));
505 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 508 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
506 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 509 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
507 RelocInfo::CODE_TARGET); 510 RelocInfo::CODE_TARGET);
508 } 511 }
509 512
510 513
511 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 514 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
512 bool is_api_function) { 515 bool is_api_function) {
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 } 900 }
898 901
899 902
900 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 903 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
901 Generate_JSEntryTrampolineHelper(masm, true); 904 Generate_JSEntryTrampolineHelper(masm, true);
902 } 905 }
903 906
904 907
905 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 908 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
906 // 1. Make sure we have at least one argument. 909 // 1. Make sure we have at least one argument.
907 // r0: actual number of argument 910 // r0: actual number of arguments
908 { Label done; 911 { Label done;
909 __ tst(r0, Operand(r0)); 912 __ tst(r0, Operand(r0));
910 __ b(ne, &done); 913 __ b(ne, &done);
911 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 914 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
912 __ push(r2); 915 __ push(r2);
913 __ add(r0, r0, Operand(1)); 916 __ add(r0, r0, Operand(1));
914 __ bind(&done); 917 __ bind(&done);
915 } 918 }
916 919
917 // 2. Get the function to call from the stack. 920 // 2. Get the function to call (passed as receiver) from the stack, check
918 // r0: actual number of argument 921 // if it is a function.
919 { Label done, non_function, function; 922 // r0: actual number of arguments
920 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 923 Label non_function;
921 __ tst(r1, Operand(kSmiTagMask)); 924 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
922 __ b(eq, &non_function); 925 __ tst(r1, Operand(kSmiTagMask));
923 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 926 __ b(eq, &non_function);
924 __ b(eq, &function); 927 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
928 __ b(ne, &non_function);
925 929
926 // Non-function called: Clear the function to force exception. 930 // 3a. Patch the first argument if necessary when calling a function.
927 __ bind(&non_function); 931 // r0: actual number of arguments
928 __ mov(r1, Operand(0)); 932 // r1: function
929 __ b(&done); 933 Label shift_arguments;
930 934 { Label convert_to_object, use_global_receiver, patch_receiver;
931 // Change the context eagerly because it will be used below to get the 935 // Change context eagerly in case we need the global receiver.
932 // right global object.
933 __ bind(&function);
934 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 936 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
935 937
936 __ bind(&done);
937 }
938
939 // 3. Make sure first argument is an object; convert if necessary.
940 // r0: actual number of arguments
941 // r1: function
942 { Label call_to_object, use_global_receiver, patch_receiver, done;
943 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 938 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
944 __ ldr(r2, MemOperand(r2, -kPointerSize)); 939 __ ldr(r2, MemOperand(r2, -kPointerSize));
945
946 // r0: actual number of arguments 940 // r0: actual number of arguments
947 // r1: function 941 // r1: function
948 // r2: first argument 942 // r2: first argument
949 __ tst(r2, Operand(kSmiTagMask)); 943 __ tst(r2, Operand(kSmiTagMask));
950 __ b(eq, &call_to_object); 944 __ b(eq, &convert_to_object);
951 945
952 __ LoadRoot(r3, Heap::kNullValueRootIndex); 946 __ LoadRoot(r3, Heap::kNullValueRootIndex);
953 __ cmp(r2, r3); 947 __ cmp(r2, r3);
954 __ b(eq, &use_global_receiver); 948 __ b(eq, &use_global_receiver);
955 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); 949 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
956 __ cmp(r2, r3); 950 __ cmp(r2, r3);
957 __ b(eq, &use_global_receiver); 951 __ b(eq, &use_global_receiver);
958 952
959 __ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE); 953 __ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE);
960 __ b(lt, &call_to_object); 954 __ b(lt, &convert_to_object);
961 __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE)); 955 __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
962 __ b(le, &done); 956 __ b(le, &shift_arguments);
963 957
964 __ bind(&call_to_object); 958 __ bind(&convert_to_object);
965 __ EnterInternalFrame(); 959 __ EnterInternalFrame(); // In order to preserve argument count.
966 960 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged.
967 // Store number of arguments and function across the call into the runtime.
968 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
969 __ push(r0); 961 __ push(r0);
970 __ push(r1);
971 962
972 __ push(r2); 963 __ push(r2);
973 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); 964 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
974 __ mov(r2, r0); 965 __ mov(r2, r0);
975 966
976 // Restore number of arguments and function.
977 __ pop(r1);
978 __ pop(r0); 967 __ pop(r0);
979 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 968 __ mov(r0, Operand(r0, ASR, kSmiTagSize));
969 __ LeaveInternalFrame();
970 // Restore the function to r1.
971 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
972 __ jmp(&patch_receiver);
980 973
981 __ LeaveInternalFrame(); 974 // Use the global receiver object from the called function as the
982 __ b(&patch_receiver); 975 // receiver.
983
984 // Use the global receiver object from the called function as the receiver.
985 __ bind(&use_global_receiver); 976 __ bind(&use_global_receiver);
986 const int kGlobalIndex = 977 const int kGlobalIndex =
987 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 978 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
988 __ ldr(r2, FieldMemOperand(cp, kGlobalIndex)); 979 __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
989 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset)); 980 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
990 __ ldr(r2, FieldMemOperand(r2, kGlobalIndex)); 981 __ ldr(r2, FieldMemOperand(r2, kGlobalIndex));
991 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); 982 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
992 983
993 __ bind(&patch_receiver); 984 __ bind(&patch_receiver);
994 __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); 985 __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
995 __ str(r2, MemOperand(r3, -kPointerSize)); 986 __ str(r2, MemOperand(r3, -kPointerSize));
996 987
997 __ bind(&done); 988 __ jmp(&shift_arguments);
998 } 989 }
999 990
1000 // 4. Shift stuff one slot down the stack 991 // 3b. Patch the first argument when calling a non-function. The
1001 // r0: actual number of arguments (including call() receiver) 992 // CALL_NON_FUNCTION builtin expects the non-function callee as
993 // receiver, so overwrite the first argument which will ultimately
994 // become the receiver.
995 // r0: actual number of arguments
1002 // r1: function 996 // r1: function
997 __ bind(&non_function);
998 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
999 __ str(r1, MemOperand(r2, -kPointerSize));
1000 // Clear r1 to indicate a non-function being called.
1001 __ mov(r1, Operand(0));
1002
1003 // 4. Shift arguments and return address one slot down on the stack
1004 // (overwriting the original receiver). Adjust argument count to make
1005 // the original first argument the new receiver.
1006 // r0: actual number of arguments
1007 // r1: function
1008 __ bind(&shift_arguments);
1003 { Label loop; 1009 { Label loop;
1004 // Calculate the copy start address (destination). Copy end address is sp. 1010 // Calculate the copy start address (destination). Copy end address is sp.
1005 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1011 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1006 __ add(r2, r2, Operand(kPointerSize)); // copy receiver too
1007 1012
1008 __ bind(&loop); 1013 __ bind(&loop);
1009 __ ldr(ip, MemOperand(r2, -kPointerSize)); 1014 __ ldr(ip, MemOperand(r2, -kPointerSize));
1010 __ str(ip, MemOperand(r2)); 1015 __ str(ip, MemOperand(r2));
1011 __ sub(r2, r2, Operand(kPointerSize)); 1016 __ sub(r2, r2, Operand(kPointerSize));
1012 __ cmp(r2, sp); 1017 __ cmp(r2, sp);
1013 __ b(ne, &loop); 1018 __ b(ne, &loop);
1019 // Adjust the actual number of arguments and remove the top element
1020 // (which is a copy of the last argument).
1021 __ sub(r0, r0, Operand(1));
1022 __ pop();
1014 } 1023 }
1015 1024
1016 // 5. Adjust the actual number of arguments and remove the top element. 1025 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin.
1017 // r0: actual number of arguments (including call() receiver)
1018 // r1: function
1019 __ sub(r0, r0, Operand(1));
1020 __ add(sp, sp, Operand(kPointerSize));
1021
1022 // 6. Get the code for the function or the non-function builtin.
1023 // If number of expected arguments matches, then call. Otherwise restart
1024 // the arguments adaptor stub.
1025 // r0: actual number of arguments 1026 // r0: actual number of arguments
1026 // r1: function 1027 // r1: function
1027 { Label invoke; 1028 { Label function;
1028 __ tst(r1, r1); 1029 __ tst(r1, r1);
1029 __ b(ne, &invoke); 1030 __ b(ne, &function);
1030 __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION 1031 __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION
1031 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 1032 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
1032 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 1033 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
1033 RelocInfo::CODE_TARGET); 1034 RelocInfo::CODE_TARGET);
1035 __ bind(&function);
1036 }
1034 1037
1035 __ bind(&invoke); 1038 // 5b. Get the code to call from the function and check that the number of
1036 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1039 // expected arguments matches what we're providing. If so, jump
1037 __ ldr(r2, 1040 // (tail-call) to the code in register edx without checking arguments.
1038 FieldMemOperand(r3, 1041 // r0: actual number of arguments
1039 SharedFunctionInfo::kFormalParameterCountOffset)); 1042 // r1: function
1040 __ ldr(r3, 1043 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1041 MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag)); 1044 __ ldr(r2,
1042 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 1045 FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
1043 __ cmp(r2, r0); // Check formal and actual parameter counts. 1046 __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
1044 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 1047 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
1045 RelocInfo::CODE_TARGET, ne); 1048 __ cmp(r2, r0); // Check formal and actual parameter counts.
1049 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
1050 RelocInfo::CODE_TARGET, ne);
1046 1051
1047 // 7. Jump to the code in r3 without checking arguments. 1052 ParameterCount expected(0);
1048 ParameterCount expected(0); 1053 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
1049 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
1050 }
1051 } 1054 }
1052 1055
1053 1056
1054 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 1057 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1055 const int kIndexOffset = -5 * kPointerSize; 1058 const int kIndexOffset = -5 * kPointerSize;
1056 const int kLimitOffset = -4 * kPointerSize; 1059 const int kLimitOffset = -4 * kPointerSize;
1057 const int kArgsOffset = 2 * kPointerSize; 1060 const int kArgsOffset = 2 * kPointerSize;
1058 const int kRecvOffset = 3 * kPointerSize; 1061 const int kRecvOffset = 3 * kPointerSize;
1059 const int kFunctionOffset = 4 * kPointerSize; 1062 const int kFunctionOffset = 4 * kPointerSize;
1060 1063
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1299 // Dont adapt arguments. 1302 // Dont adapt arguments.
1300 // ------------------------------------------- 1303 // -------------------------------------------
1301 __ bind(&dont_adapt_arguments); 1304 __ bind(&dont_adapt_arguments);
1302 __ Jump(r3); 1305 __ Jump(r3);
1303 } 1306 }
1304 1307
1305 1308
1306 #undef __ 1309 #undef __
1307 1310
1308 } } // namespace v8::internal 1311 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/assembler-thumb2-inl.h ('k') | src/arm/codegen-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698