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

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 6248004: ARM: Implement DoInstanceOfKnownGlobal stub (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 11 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 | « no previous file | src/arm/lithium-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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 2872 matching lines...) Expand 10 before | Expand all | Expand 10 after
2883 // Restore callee-saved registers and return. 2883 // Restore callee-saved registers and return.
2884 #ifdef DEBUG 2884 #ifdef DEBUG
2885 if (FLAG_debug_code) { 2885 if (FLAG_debug_code) {
2886 __ mov(lr, Operand(pc)); 2886 __ mov(lr, Operand(pc));
2887 } 2887 }
2888 #endif 2888 #endif
2889 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); 2889 __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
2890 } 2890 }
2891 2891
2892 2892
2893 // Uses registers r0 to r4. Expected input is 2893 // Uses registers r0 to r4.
2894 // object in r0 (or at sp+1*kPointerSize) and function in 2894 // Expected input (depending on whether args are in registers or on the stack):
2895 // r1 (or at sp), depending on whether or not 2895 // * object: r0 or at sp + 1 * kPointerSize.
2896 // args_in_registers() is true. 2896 // * function: r1 or at sp.
2897 //
2898 // An inlined call site may have been generated before calling this stub.
2899 // In this case the offset to the inline site to patch is passed on the stack,
2900 // in the safepoint slot for register r4.
2901 // (See LCodeGen::DoInstanceOfKnownGlobal)
2897 void InstanceofStub::Generate(MacroAssembler* masm) { 2902 void InstanceofStub::Generate(MacroAssembler* masm) {
2903 // Call site inlining and patching implies arguments in registers.
2904 ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck());
2905 // ReturnTrueFalse is only implemented for inlined call sites.
2906 ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck());
2907
2898 // Fixed register usage throughout the stub: 2908 // Fixed register usage throughout the stub:
2899 const Register object = r0; // Object (lhs). 2909 const Register object = r0; // Object (lhs).
2900 const Register map = r3; // Map of the object. 2910 Register map = r3; // Map of the object.
2901 const Register function = r1; // Function (rhs). 2911 const Register function = r1; // Function (rhs).
2902 const Register prototype = r4; // Prototype of the function. 2912 const Register prototype = r4; // Prototype of the function.
2913 const Register inline_site = r9;
2903 const Register scratch = r2; 2914 const Register scratch = r2;
2915
2916 const int32_t kDeltaToLoadBoolResult = 3 * kPointerSize;
2917
2904 Label slow, loop, is_instance, is_not_instance, not_js_object; 2918 Label slow, loop, is_instance, is_not_instance, not_js_object;
2919
2905 if (!HasArgsInRegisters()) { 2920 if (!HasArgsInRegisters()) {
2906 __ ldr(object, MemOperand(sp, 1 * kPointerSize)); 2921 __ ldr(object, MemOperand(sp, 1 * kPointerSize));
2907 __ ldr(function, MemOperand(sp, 0)); 2922 __ ldr(function, MemOperand(sp, 0));
2908 } 2923 }
2909 2924
2910 // Check that the left hand is a JS object and load map. 2925 // Check that the left hand is a JS object and load map.
2911 __ BranchOnSmi(object, &not_js_object); 2926 __ BranchOnSmi(object, &not_js_object);
2912 __ IsObjectJSObjectType(object, map, scratch, &not_js_object); 2927 __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
2913 2928
2914 // Look up the function and the map in the instanceof cache. 2929 // If there is a call site cache don't look in the global cache, but do the
2915 Label miss; 2930 // real lookup and update the call site cache.
2916 __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex); 2931 if (!HasCallSiteInlineCheck()) {
2917 __ cmp(function, ip); 2932 Label miss;
2918 __ b(ne, &miss); 2933 __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex);
2919 __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex); 2934 __ cmp(function, ip);
2920 __ cmp(map, ip); 2935 __ b(ne, &miss);
2921 __ b(ne, &miss); 2936 __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex);
2922 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 2937 __ cmp(map, ip);
2923 __ Ret(HasArgsInRegisters() ? 0 : 2); 2938 __ b(ne, &miss);
2939 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
2940 __ Ret(HasArgsInRegisters() ? 0 : 2);
2924 2941
2925 __ bind(&miss); 2942 __ bind(&miss);
2943 }
2944
2945 // Get the prototype of the function.
2926 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); 2946 __ TryGetFunctionPrototype(function, prototype, scratch, &slow);
2927 2947
2928 // Check that the function prototype is a JS object. 2948 // Check that the function prototype is a JS object.
2929 __ BranchOnSmi(prototype, &slow); 2949 __ BranchOnSmi(prototype, &slow);
2930 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); 2950 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
2931 2951
2932 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 2952 // Update the global instanceof or call site inlined cache with the current
2933 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); 2953 // map and function. The cached answer will be set when it is known below.
2954 if (!HasCallSiteInlineCheck()) {
2955 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
2956 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
2957 } else {
2958 ASSERT(HasArgsInRegisters());
2959 // Patch the (relocated) inlined map check.
2960
2961 // The offset was stored in r4 safepoint slot.
2962 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal)
2963 __ ldr(scratch, MacroAssembler::SafepointRegisterSlot(r4));
2964 __ sub(inline_site, lr, scratch);
2965 // Get the map location in scratch and patch it.
2966 __ GetRelocatedValueLocation(inline_site, scratch);
2967 __ str(map, MemOperand(scratch));
2968 }
2934 2969
2935 // Register mapping: r3 is object map and r4 is function prototype. 2970 // Register mapping: r3 is object map and r4 is function prototype.
2936 // Get prototype of object into r2. 2971 // Get prototype of object into r2.
2937 __ ldr(scratch, FieldMemOperand(map, Map::kPrototypeOffset)); 2972 __ ldr(scratch, FieldMemOperand(map, Map::kPrototypeOffset));
2938 2973
2974 // We don't need map any more. Use it as a scratch register.
2975 Register scratch2 = map;
2976 map = no_reg;
2977
2939 // Loop through the prototype chain looking for the function prototype. 2978 // Loop through the prototype chain looking for the function prototype.
2979 __ LoadRoot(scratch2, Heap::kNullValueRootIndex);
2940 __ bind(&loop); 2980 __ bind(&loop);
2941 __ cmp(scratch, Operand(prototype)); 2981 __ cmp(scratch, Operand(prototype));
2942 __ b(eq, &is_instance); 2982 __ b(eq, &is_instance);
2943 __ LoadRoot(ip, Heap::kNullValueRootIndex); 2983 __ cmp(scratch, scratch2);
2944 __ cmp(scratch, ip);
2945 __ b(eq, &is_not_instance); 2984 __ b(eq, &is_not_instance);
2946 __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); 2985 __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
2947 __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); 2986 __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
2948 __ jmp(&loop); 2987 __ jmp(&loop);
2949 2988
2950 __ bind(&is_instance); 2989 __ bind(&is_instance);
2951 __ mov(r0, Operand(Smi::FromInt(0))); 2990 if (!HasCallSiteInlineCheck()) {
2952 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 2991 __ mov(r0, Operand(Smi::FromInt(0)));
2992 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
2993 } else {
2994 // Patch the call site to return true.
2995 __ LoadRoot(r0, Heap::kTrueValueRootIndex);
2996 __ add(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
2997 // Get the boolean result location in scratch and patch it.
2998 __ GetRelocatedValueLocation(inline_site, scratch);
2999 __ str(r0, MemOperand(scratch));
3000
3001 if (!ReturnTrueFalseObject()) {
3002 __ mov(r0, Operand(Smi::FromInt(0)));
3003 }
3004 }
2953 __ Ret(HasArgsInRegisters() ? 0 : 2); 3005 __ Ret(HasArgsInRegisters() ? 0 : 2);
2954 3006
2955 __ bind(&is_not_instance); 3007 __ bind(&is_not_instance);
2956 __ mov(r0, Operand(Smi::FromInt(1))); 3008 if (!HasCallSiteInlineCheck()) {
2957 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 3009 __ mov(r0, Operand(Smi::FromInt(1)));
3010 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
3011 } else {
3012 // Patch the call site to return false.
3013 __ LoadRoot(r0, Heap::kFalseValueRootIndex);
3014 __ add(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
3015 // Get the boolean result location in scratch and patch it.
3016 __ GetRelocatedValueLocation(inline_site, scratch);
3017 __ str(r0, MemOperand(scratch));
3018
3019 if (!ReturnTrueFalseObject()) {
3020 __ mov(r0, Operand(Smi::FromInt(1)));
3021 }
3022 }
2958 __ Ret(HasArgsInRegisters() ? 0 : 2); 3023 __ Ret(HasArgsInRegisters() ? 0 : 2);
2959 3024
2960 Label object_not_null, object_not_null_or_smi; 3025 Label object_not_null, object_not_null_or_smi;
2961 __ bind(&not_js_object); 3026 __ bind(&not_js_object);
2962 // Before null, smi and string value checks, check that the rhs is a function 3027 // Before null, smi and string value checks, check that the rhs is a function
2963 // as for a non-function rhs an exception needs to be thrown. 3028 // as for a non-function rhs an exception needs to be thrown.
2964 __ BranchOnSmi(function, &slow); 3029 __ BranchOnSmi(function, &slow);
2965 __ CompareObjectType(function, map, scratch, JS_FUNCTION_TYPE); 3030 __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE);
2966 __ b(ne, &slow); 3031 __ b(ne, &slow);
2967 3032
2968 // Null is not instance of anything. 3033 // Null is not instance of anything.
2969 __ cmp(scratch, Operand(Factory::null_value())); 3034 __ cmp(scratch, Operand(Factory::null_value()));
2970 __ b(ne, &object_not_null); 3035 __ b(ne, &object_not_null);
2971 __ mov(r0, Operand(Smi::FromInt(1))); 3036 __ mov(r0, Operand(Smi::FromInt(1)));
2972 __ Ret(HasArgsInRegisters() ? 0 : 2); 3037 __ Ret(HasArgsInRegisters() ? 0 : 2);
2973 3038
2974 __ bind(&object_not_null); 3039 __ bind(&object_not_null);
2975 // Smi values are not instances of anything. 3040 // Smi values are not instances of anything.
2976 __ BranchOnNotSmi(object, &object_not_null_or_smi); 3041 __ BranchOnNotSmi(object, &object_not_null_or_smi);
2977 __ mov(r0, Operand(Smi::FromInt(1))); 3042 __ mov(r0, Operand(Smi::FromInt(1)));
2978 __ Ret(HasArgsInRegisters() ? 0 : 2); 3043 __ Ret(HasArgsInRegisters() ? 0 : 2);
2979 3044
2980 __ bind(&object_not_null_or_smi); 3045 __ bind(&object_not_null_or_smi);
2981 // String values are not instances of anything. 3046 // String values are not instances of anything.
2982 __ IsObjectJSStringType(object, scratch, &slow); 3047 __ IsObjectJSStringType(object, scratch, &slow);
2983 __ mov(r0, Operand(Smi::FromInt(1))); 3048 __ mov(r0, Operand(Smi::FromInt(1)));
2984 __ Ret(HasArgsInRegisters() ? 0 : 2); 3049 __ Ret(HasArgsInRegisters() ? 0 : 2);
2985 3050
2986 // Slow-case. Tail call builtin. 3051 // Slow-case. Tail call builtin.
2987 __ bind(&slow); 3052 __ bind(&slow);
2988 if (HasArgsInRegisters()) { 3053 if (!ReturnTrueFalseObject()) {
3054 if (HasArgsInRegisters()) {
3055 __ Push(r0, r1);
3056 }
3057 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_JS);
3058 } else {
3059 __ EnterInternalFrame();
2989 __ Push(r0, r1); 3060 __ Push(r0, r1);
3061 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_JS);
3062 __ LeaveInternalFrame();
3063 __ cmp(r0, Operand(0));
3064 __ LoadRoot(r0, Heap::kTrueValueRootIndex, eq);
3065 __ LoadRoot(r0, Heap::kFalseValueRootIndex, ne);
3066 __ Ret(HasArgsInRegisters() ? 0 : 2);
2990 } 3067 }
2991 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_JS);
2992 } 3068 }
2993 3069
2994 3070
3071 Register InstanceofStub::left() { return r0; }
3072
3073
3074 Register InstanceofStub::right() { return r1; }
3075
3076
2995 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 3077 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
2996 // The displacement is the offset of the last parameter (if any) 3078 // The displacement is the offset of the last parameter (if any)
2997 // relative to the frame pointer. 3079 // relative to the frame pointer.
2998 static const int kDisplacement = 3080 static const int kDisplacement =
2999 StandardFrameConstants::kCallerSPOffset - kPointerSize; 3081 StandardFrameConstants::kCallerSPOffset - kPointerSize;
3000 3082
3001 // Check that the key is a smi. 3083 // Check that the key is a smi.
3002 Label slow; 3084 Label slow;
3003 __ BranchOnNotSmi(r1, &slow); 3085 __ BranchOnNotSmi(r1, &slow);
3004 3086
(...skipping 2020 matching lines...) Expand 10 before | Expand all | Expand 10 after
5025 __ pop(r1); 5107 __ pop(r1);
5026 __ Jump(r2); 5108 __ Jump(r2);
5027 } 5109 }
5028 5110
5029 5111
5030 #undef __ 5112 #undef __
5031 5113
5032 } } // namespace v8::internal 5114 } } // namespace v8::internal
5033 5115
5034 #endif // V8_TARGET_ARCH_ARM 5116 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/arm/lithium-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698