1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_IC_HANDLER_COMPILER_H_ 6 #define V8_IC_HANDLER_COMPILER_H_ 7 8 #include "src/ic/access-compiler.h" 9 #include "src/ic/ic-state.h" 10 11 namespace v8 { 12 namespace internal { 13 14 class CallOptimization; 15 16 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER }; 17 18 class PropertyHandlerCompiler : public PropertyAccessCompiler { 19 public: 20 static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind, 21 CacheHolderFlag cache_holder, Code::StubType type); 22 23 protected: PropertyHandlerCompiler(Isolate * isolate,Code::Kind kind,Handle<HeapType> type,Handle<JSObject> holder,CacheHolderFlag cache_holder)24 PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, 25 Handle<HeapType> type, Handle<JSObject> holder, 26 CacheHolderFlag cache_holder) 27 : PropertyAccessCompiler(isolate, kind, cache_holder), 28 type_(type), 29 holder_(holder) {} 30 ~PropertyHandlerCompiler()31 virtual ~PropertyHandlerCompiler() {} 32 FrontendHeader(Register object_reg,Handle<Name> name,Label * miss)33 virtual Register FrontendHeader(Register object_reg, Handle<Name> name, 34 Label* miss) { 35 UNREACHABLE(); 36 return receiver(); 37 } 38 FrontendFooter(Handle<Name> name,Label * miss)39 virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); } 40 41 Register Frontend(Register object_reg, Handle<Name> name); 42 void NonexistentFrontendHeader(Handle<Name> name, Label* miss, 43 Register scratch1, Register scratch2); 44 45 // TODO(verwaest): Make non-static. 46 static void GenerateFastApiCall(MacroAssembler* masm, 47 const CallOptimization& optimization, 48 Handle<Map> receiver_map, Register receiver, 49 Register scratch, bool is_store, int argc, 50 Register* values); 51 52 // Helper function used to check that the dictionary doesn't contain 53 // the property. This function may return false negatives, so miss_label 54 // must always call a backup property check that is complete. 55 // This function is safe to call if the receiver has fast properties. 56 // Name must be unique and receiver must be a heap object. 57 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 58 Label* miss_label, 59 Register receiver, 60 Handle<Name> name, Register r0, 61 Register r1); 62 63 // Generate code to check that a global property cell is empty. Create 64 // the property cell at compilation time if no cell exists for the 65 // property. 66 static void GenerateCheckPropertyCell(MacroAssembler* masm, 67 Handle<JSGlobalObject> global, 68 Handle<Name> name, Register scratch, 69 Label* miss); 70 71 // Generates code that verifies that the property holder has not changed 72 // (checking maps of objects in the prototype chain for fast and global 73 // objects or doing negative lookup for slow objects, ensures that the 74 // property cells for global objects are still empty) and checks that the map 75 // of the holder has not changed. If necessary the function also generates 76 // code for security check in case of global object holders. Helps to make 77 // sure that the current IC is still valid. 78 // 79 // The scratch and holder registers are always clobbered, but the object 80 // register is only clobbered if it the same as the holder register. The 81 // function returns a register containing the holder - either object_reg or 82 // holder_reg. 83 Register CheckPrototypes(Register object_reg, Register holder_reg, 84 Register scratch1, Register scratch2, 85 Handle<Name> name, Label* miss, 86 PrototypeCheckType check = CHECK_ALL_MAPS); 87 88 Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name); 89 void set_type_for_object(Handle<Object> object); set_holder(Handle<JSObject> holder)90 void set_holder(Handle<JSObject> holder) { holder_ = holder; } type()91 Handle<HeapType> type() const { return type_; } holder()92 Handle<JSObject> holder() const { return holder_; } 93 94 private: 95 Handle<HeapType> type_; 96 Handle<JSObject> holder_; 97 }; 98 99 100 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { 101 public: NamedLoadHandlerCompiler(Isolate * isolate,Handle<HeapType> type,Handle<JSObject> holder,CacheHolderFlag cache_holder)102 NamedLoadHandlerCompiler(Isolate* isolate, Handle<HeapType> type, 103 Handle<JSObject> holder, 104 CacheHolderFlag cache_holder) 105 : PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, holder, 106 cache_holder) {} 107 ~NamedLoadHandlerCompiler()108 virtual ~NamedLoadHandlerCompiler() {} 109 110 Handle<Code> CompileLoadField(Handle<Name> name, FieldIndex index); 111 112 Handle<Code> CompileLoadCallback(Handle<Name> name, 113 Handle<ExecutableAccessorInfo> callback); 114 115 Handle<Code> CompileLoadCallback(Handle<Name> name, 116 const CallOptimization& call_optimization); 117 118 Handle<Code> CompileLoadConstant(Handle<Name> name, int constant_index); 119 120 // The LookupIterator is used to perform a lookup behind the interceptor. If 121 // the iterator points to a LookupIterator::PROPERTY, its access will be 122 // inlined. 123 Handle<Code> CompileLoadInterceptor(LookupIterator* it); 124 125 Handle<Code> CompileLoadViaGetter(Handle<Name> name, 126 Handle<JSFunction> getter); 127 128 Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name, 129 bool is_configurable); 130 131 // Static interface 132 static Handle<Code> ComputeLoadNonexistent(Handle<Name> name, 133 Handle<HeapType> type); 134 135 static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<HeapType> type, 136 Register receiver, 137 Handle<JSFunction> getter); 138 GenerateLoadViaGetterForDeopt(MacroAssembler * masm)139 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) { 140 GenerateLoadViaGetter(masm, Handle<HeapType>::null(), no_reg, 141 Handle<JSFunction>()); 142 } 143 144 static void GenerateLoadFunctionPrototype(MacroAssembler* masm, 145 Register receiver, 146 Register scratch1, 147 Register scratch2, 148 Label* miss_label); 149 150 // These constants describe the structure of the interceptor arguments on the 151 // stack. The arguments are pushed by the (platform-specific) 152 // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and 153 // LoadWithInterceptor. 154 static const int kInterceptorArgsNameIndex = 0; 155 static const int kInterceptorArgsInfoIndex = 1; 156 static const int kInterceptorArgsThisIndex = 2; 157 static const int kInterceptorArgsHolderIndex = 3; 158 static const int kInterceptorArgsLength = 4; 159 160 protected: 161 virtual Register FrontendHeader(Register object_reg, Handle<Name> name, 162 Label* miss); 163 164 virtual void FrontendFooter(Handle<Name> name, Label* miss); 165 166 private: 167 Handle<Code> CompileLoadNonexistent(Handle<Name> name); 168 void GenerateLoadConstant(Handle<Object> value); 169 void GenerateLoadCallback(Register reg, 170 Handle<ExecutableAccessorInfo> callback); 171 void GenerateLoadCallback(const CallOptimization& call_optimization, 172 Handle<Map> receiver_map); 173 void GenerateLoadInterceptor(Register holder_reg); 174 void GenerateLoadInterceptorWithFollowup(LookupIterator* it, 175 Register holder_reg); 176 void GenerateLoadPostInterceptor(LookupIterator* it, Register reg); 177 178 // Generates prototype loading code that uses the objects from the 179 // context we were in when this function was called. If the context 180 // has changed, a jump to miss is performed. This ties the generated 181 // code to a particular context and so must not be used in cases 182 // where the generated code is not allowed to have references to 183 // objects from a context. 184 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm, 185 int index, 186 Register prototype, 187 Label* miss); 188 189 scratch4()190 Register scratch4() { return registers_[5]; } 191 }; 192 193 194 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { 195 public: NamedStoreHandlerCompiler(Isolate * isolate,Handle<HeapType> type,Handle<JSObject> holder)196 explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<HeapType> type, 197 Handle<JSObject> holder) 198 : PropertyHandlerCompiler(isolate, Code::STORE_IC, type, holder, 199 kCacheOnReceiver) {} 200 ~NamedStoreHandlerCompiler()201 virtual ~NamedStoreHandlerCompiler() {} 202 203 Handle<Code> CompileStoreTransition(Handle<Map> transition, 204 Handle<Name> name); 205 Handle<Code> CompileStoreField(LookupIterator* it); 206 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name, 207 Handle<ExecutableAccessorInfo> callback); 208 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name, 209 const CallOptimization& call_optimization); 210 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name, 211 Handle<JSFunction> setter); 212 Handle<Code> CompileStoreInterceptor(Handle<Name> name); 213 214 static void GenerateStoreViaSetter(MacroAssembler* masm, 215 Handle<HeapType> type, Register receiver, 216 Handle<JSFunction> setter); 217 GenerateStoreViaSetterForDeopt(MacroAssembler * masm)218 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) { 219 GenerateStoreViaSetter(masm, Handle<HeapType>::null(), no_reg, 220 Handle<JSFunction>()); 221 } 222 223 static void GenerateSlow(MacroAssembler* masm); 224 225 protected: 226 virtual Register FrontendHeader(Register object_reg, Handle<Name> name, 227 Label* miss); 228 229 virtual void FrontendFooter(Handle<Name> name, Label* miss); 230 void GenerateRestoreName(Label* label, Handle<Name> name); 231 232 private: 233 void GenerateStoreTransition(Handle<Map> transition, Handle<Name> name, 234 Register receiver_reg, Register name_reg, 235 Register value_reg, Register scratch1, 236 Register scratch2, Register scratch3, 237 Label* miss_label, Label* slow); 238 239 void GenerateStoreField(LookupIterator* lookup, Register value_reg, 240 Label* miss_label); 241 SlowBuiltin(Code::Kind kind)242 static Builtins::Name SlowBuiltin(Code::Kind kind) { 243 switch (kind) { 244 case Code::STORE_IC: 245 return Builtins::kStoreIC_Slow; 246 case Code::KEYED_STORE_IC: 247 return Builtins::kKeyedStoreIC_Slow; 248 default: 249 UNREACHABLE(); 250 } 251 return Builtins::kStoreIC_Slow; 252 } 253 254 static Register value(); 255 }; 256 257 258 class ElementHandlerCompiler : public PropertyHandlerCompiler { 259 public: ElementHandlerCompiler(Isolate * isolate)260 explicit ElementHandlerCompiler(Isolate* isolate) 261 : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC, 262 Handle<HeapType>::null(), 263 Handle<JSObject>::null(), kCacheOnReceiver) {} 264 ~ElementHandlerCompiler()265 virtual ~ElementHandlerCompiler() {} 266 267 void CompileElementHandlers(MapHandleList* receiver_maps, 268 CodeHandleList* handlers); 269 270 static void GenerateStoreSlow(MacroAssembler* masm); 271 }; 272 } 273 } // namespace v8::internal 274 275 #endif // V8_IC_HANDLER_COMPILER_H_ 276