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

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

Issue 136203005: A64: Implement patchable inline code for InstanceOfKnownGlobal. (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/assembler-a64.h ('k') | src/a64/lithium-codegen-a64.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 2984 matching lines...) Expand 10 before | Expand all | Expand 10 after
2995 2995
2996 2996
2997 void InstanceofStub::Generate(MacroAssembler* masm) { 2997 void InstanceofStub::Generate(MacroAssembler* masm) {
2998 // Stack on entry: 2998 // Stack on entry:
2999 // jssp[0]: function. 2999 // jssp[0]: function.
3000 // jssp[8]: object. 3000 // jssp[8]: object.
3001 // 3001 //
3002 // Returns result in x0. Zero indicates instanceof, smi 1 indicates not 3002 // Returns result in x0. Zero indicates instanceof, smi 1 indicates not
3003 // instanceof. 3003 // instanceof.
3004 3004
3005 // Instanceof supports the kArgsInRegisters flag but not the others, ie.
3006 // No call site inlining.
3007 // No return of true/false objects.
3008 ASSERT((flags_ == kNoFlags) || (flags_ == kArgsInRegisters));
3009
3010 Register result = x0; 3005 Register result = x0;
3011 Register function = right(); 3006 Register function = right();
3012 Register object = left(); 3007 Register object = left();
3008 Register scratch1 = x6;
3009 Register scratch2 = x7;
3010 Register res_true = x8;
3011 Register res_false = x9;
3012 // Only used if there was an inline map check site. (See
3013 // LCodeGen::DoInstanceOfKnownGlobal().)
3014 Register map_check_site = x4;
3015 // Delta for the instructions generated between the inline map check and the
3016 // instruction setting the result.
3017 const int32_t kDeltaToLoadBoolResult = 4 * kInstructionSize;
3018
3013 Label not_js_object, slow; 3019 Label not_js_object, slow;
3014 3020
3015 if (!HasArgsInRegisters()) { 3021 if (!HasArgsInRegisters()) {
3016 __ Pop(function, object); 3022 __ Pop(function, object);
3017 } 3023 }
3018 3024
3025 if (ReturnTrueFalseObject()) {
3026 __ LoadTrueFalseRoots(res_true, res_false);
3027 } else {
3028 // This is counter-intuitive, but correct.
3029 __ Mov(res_true, Operand(Smi::FromInt(0)));
3030 __ Mov(res_false, Operand(Smi::FromInt(1)));
3031 }
3032
3019 // Check that the left hand side is a JS object and load its map as a side 3033 // Check that the left hand side is a JS object and load its map as a side
3020 // effect. 3034 // effect.
3021 Register map = x12; 3035 Register map = x12;
3022 __ JumpIfSmi(object, &not_js_object); 3036 __ JumpIfSmi(object, &not_js_object);
3023 __ IsObjectJSObjectType(object, map, x7, &not_js_object); 3037 __ IsObjectJSObjectType(object, map, scratch2, &not_js_object);
3024 3038
3025 // If there is a call site cache, don't look in the global cache, but do the 3039 // If there is a call site cache, don't look in the global cache, but do the
3026 // real lookup and update the call site cache. 3040 // real lookup and update the call site cache.
3027 if (!HasCallSiteInlineCheck()) { 3041 if (!HasCallSiteInlineCheck()) {
3028 Label miss; 3042 Label miss;
3029 __ JumpIfNotRoot(function, Heap::kInstanceofCacheFunctionRootIndex, &miss); 3043 __ JumpIfNotRoot(function, Heap::kInstanceofCacheFunctionRootIndex, &miss);
3030 __ JumpIfNotRoot(map, Heap::kInstanceofCacheMapRootIndex, &miss); 3044 __ JumpIfNotRoot(map, Heap::kInstanceofCacheMapRootIndex, &miss);
3031 __ LoadRoot(result, Heap::kInstanceofCacheAnswerRootIndex); 3045 __ LoadRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
3032 __ Ret(); 3046 __ Ret();
3033 __ Bind(&miss); 3047 __ Bind(&miss);
3034 } 3048 }
3035 3049
3036 // Get the prototype of the function. 3050 // Get the prototype of the function.
3037 Register prototype = x13; 3051 Register prototype = x13;
3038 __ TryGetFunctionPrototype(function, prototype, x7, &slow, 3052 __ TryGetFunctionPrototype(function, prototype, scratch2, &slow,
3039 MacroAssembler::kMissOnBoundFunction); 3053 MacroAssembler::kMissOnBoundFunction);
3040 3054
3041 // Check that the function prototype is a JS object. 3055 // Check that the function prototype is a JS object.
3042 __ JumpIfSmi(prototype, &slow); 3056 __ JumpIfSmi(prototype, &slow);
3043 __ IsObjectJSObjectType(prototype, x6, x7, &slow); 3057 __ IsObjectJSObjectType(prototype, scratch1, scratch2, &slow);
3044 3058
3045 // Update the global instanceof or call site inlined cache with the current 3059 // Update the global instanceof or call site inlined cache with the current
3046 // map and function. The cached answer will be set when it is known below. 3060 // map and function. The cached answer will be set when it is known below.
3047 if (!HasCallSiteInlineCheck()) { 3061 if (HasCallSiteInlineCheck()) {
3062 // Patch the (relocated) inlined map check.
3063 __ GetRelocatedValueLocation(map_check_site, scratch1);
3064 // We have a cell, so need another level of dereferencing.
3065 __ Ldr(scratch1, MemOperand(scratch1));
3066 __ Str(map, FieldMemOperand(scratch1, Cell::kValueOffset));
3067 } else {
3048 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 3068 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
3049 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); 3069 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
3050 } else {
3051 ASM_UNIMPLEMENTED("InstanceofStub inline patching");
3052 } 3070 }
3053 3071
3054 Label return_result; 3072 Label return_true, return_result;
3055 { 3073 {
3056 // Loop through the prototype chain looking for the function prototype. 3074 // Loop through the prototype chain looking for the function prototype.
3057 Register chain_map = x1; 3075 Register chain_map = x1;
3058 Register chain_prototype = x14; 3076 Register chain_prototype = x14;
3059 Register null_value = x15; 3077 Register null_value = x15;
3060 Label loop; 3078 Label loop;
3061 __ Ldr(chain_prototype, FieldMemOperand(map, Map::kPrototypeOffset)); 3079 __ Ldr(chain_prototype, FieldMemOperand(map, Map::kPrototypeOffset));
3062 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 3080 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
3063 // Speculatively set a result. 3081 // Speculatively set a result.
3064 __ Mov(result, Operand(Smi::FromInt(1))); 3082 __ Mov(result, res_false);
3065 3083
3066 __ Bind(&loop); 3084 __ Bind(&loop);
3067 3085
3068 // If the chain prototype is the object prototype, return smi(0). 3086 // If the chain prototype is the object prototype, return true.
3069 __ Cmp(chain_prototype, prototype); 3087 __ Cmp(chain_prototype, prototype);
3070 ASSERT(Smi::FromInt(0) == 0UL); 3088 __ B(eq, &return_true);
3071 __ CzeroX(result, eq);
3072 __ B(eq, &return_result);
3073 3089
3074 // If the chain prototype is null, we've reached the end of the chain, so 3090 // If the chain prototype is null, we've reached the end of the chain, so
3075 // return smi(1). 3091 // return false.
3076 __ Cmp(chain_prototype, null_value); 3092 __ Cmp(chain_prototype, null_value);
3077 __ B(eq, &return_result); 3093 __ B(eq, &return_result);
3078 3094
3079 // Otherwise, load the next prototype in the chain, and loop. 3095 // Otherwise, load the next prototype in the chain, and loop.
3080 __ Ldr(chain_map, FieldMemOperand(chain_prototype, HeapObject::kMapOffset)); 3096 __ Ldr(chain_map, FieldMemOperand(chain_prototype, HeapObject::kMapOffset));
3081 __ Ldr(chain_prototype, FieldMemOperand(chain_map, Map::kPrototypeOffset)); 3097 __ Ldr(chain_prototype, FieldMemOperand(chain_map, Map::kPrototypeOffset));
3082 __ B(&loop); 3098 __ B(&loop);
3083 } 3099 }
3084 3100
3085 // Return sequence when no arguments are on the stack. 3101 // Return sequence when no arguments are on the stack.
3102 // We cannot fall through to here.
3103 __ Bind(&return_true);
3104 __ Mov(result, res_true);
3086 __ Bind(&return_result); 3105 __ Bind(&return_result);
3087 if (!HasCallSiteInlineCheck()) { 3106 if (HasCallSiteInlineCheck()) {
3107 ASSERT(ReturnTrueFalseObject());
3108 __ Add(map_check_site, map_check_site, kDeltaToLoadBoolResult);
3109 __ GetRelocatedValueLocation(map_check_site, scratch2);
3110 __ Str(result, MemOperand(scratch2));
3111 } else {
3088 __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex); 3112 __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
3089 } else {
3090 ASM_UNIMPLEMENTED("InstanceofStub call site patcher");
3091 } 3113 }
3092 __ Ret(); 3114 __ Ret();
3093 3115
3094 Label object_not_null, object_not_null_or_smi; 3116 Label object_not_null, object_not_null_or_smi;
3095 3117
3096 __ Bind(&not_js_object); 3118 __ Bind(&not_js_object);
3097 Register object_type = x14; 3119 Register object_type = x14;
3098 // x0 result result return register (uninit) 3120 // x0 result result return register (uninit)
3099 // x10 function pointer to function 3121 // x10 function pointer to function
3100 // x11 object pointer to object 3122 // x11 object pointer to object
3101 // x14 object_type type of object (uninit) 3123 // x14 object_type type of object (uninit)
3102 3124
3103 // Before null, smi and string checks, check that the rhs is a function. 3125 // Before null, smi and string checks, check that the rhs is a function.
3104 // For a non-function rhs, an exception must be thrown. 3126 // For a non-function rhs, an exception must be thrown.
3105 __ JumpIfSmi(function, &slow); 3127 __ JumpIfSmi(function, &slow);
3106 __ JumpIfNotObjectType(function, x6, object_type, JS_FUNCTION_TYPE, &slow); 3128 __ JumpIfNotObjectType(
3129 function, scratch1, object_type, JS_FUNCTION_TYPE, &slow);
3130
3131 __ Mov(result, res_false);
3107 3132
3108 // Null is not instance of anything. 3133 // Null is not instance of anything.
3109 __ Cmp(object_type, Operand(masm->isolate()->factory()->null_value())); 3134 __ Cmp(object_type, Operand(masm->isolate()->factory()->null_value()));
3110 __ B(ne, &object_not_null); 3135 __ B(ne, &object_not_null);
3111 __ Mov(result, Operand(Smi::FromInt(1)));
3112 __ Ret(); 3136 __ Ret();
3113 3137
3114 __ Bind(&object_not_null); 3138 __ Bind(&object_not_null);
3115 // Smi values are not instances of anything. 3139 // Smi values are not instances of anything.
3116 __ JumpIfNotSmi(object, &object_not_null_or_smi); 3140 __ JumpIfNotSmi(object, &object_not_null_or_smi);
3117 __ Mov(result, Operand(Smi::FromInt(1)));
3118 __ Ret(); 3141 __ Ret();
3119 3142
3120 __ Bind(&object_not_null_or_smi); 3143 __ Bind(&object_not_null_or_smi);
3121 // String values are not instances of anything. 3144 // String values are not instances of anything.
3122 __ IsObjectJSStringType(object, x7, &slow); 3145 __ IsObjectJSStringType(object, scratch2, &slow);
3123 __ Mov(result, Operand(Smi::FromInt(1)));
3124 __ Ret(); 3146 __ Ret();
3125 3147
3126 // Slow-case. Tail call builtin. 3148 // Slow-case. Tail call builtin.
3127 __ Bind(&slow); 3149 __ Bind(&slow);
3128 if (!ReturnTrueFalseObject()) { 3150 {
3129 FrameScope scope(masm, StackFrame::INTERNAL); 3151 FrameScope scope(masm, StackFrame::INTERNAL);
3130 // Arguments have either been passed into registers or have been previously 3152 // Arguments have either been passed into registers or have been previously
3131 // popped. We need to push them before calling builtin. 3153 // popped. We need to push them before calling builtin.
3132 __ Push(object, function); 3154 __ Push(object, function);
3133 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 3155 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
3134 } else { 3156 }
3135 ASM_UNIMPLEMENTED("InstanceofStub call builtin and return object"); 3157 if (ReturnTrueFalseObject()) {
3158 __ Cmp(result, 0);
3159 __ Csel(result, res_true, res_false, eq);
3136 } 3160 }
3137 __ Ret(); 3161 __ Ret();
3138 } 3162 }
3139 3163
3140 3164
3141 Register InstanceofStub::left() { 3165 Register InstanceofStub::left() {
3142 // Object to check (instanceof lhs). 3166 // Object to check (instanceof lhs).
3143 return x11; 3167 return x11;
3144 } 3168 }
3145 3169
(...skipping 3894 matching lines...) Expand 10 before | Expand all | Expand 10 after
7040 __ Bind(&fast_elements_case); 7064 __ Bind(&fast_elements_case);
7041 GenerateCase(masm, FAST_ELEMENTS); 7065 GenerateCase(masm, FAST_ELEMENTS);
7042 } 7066 }
7043 7067
7044 7068
7045 #undef __ 7069 #undef __
7046 7070
7047 } } // namespace v8::internal 7071 } } // namespace v8::internal
7048 7072
7049 #endif // V8_TARGET_ARCH_A64 7073 #endif // V8_TARGET_ARCH_A64
OLDNEW
« no previous file with comments | « src/a64/assembler-a64.h ('k') | src/a64/lithium-codegen-a64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698