blob: 525889b80b81735b31a3d346ffcc1edfc4744607 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
11namespace v8 {
12namespace internal {
13
14class CallOptimization;
15
16enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
Ben Murdoch014dc512016-03-22 12:00:34 +000017enum ReturnHolder { RETURN_HOLDER, DONT_RETURN_ANYTHING };
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018
19class PropertyHandlerCompiler : public PropertyAccessCompiler {
20 public:
21 static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind,
Ben Murdochbcf72ee2016-08-08 18:44:38 +010022 CacheHolderFlag cache_holder);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023
24 protected:
Ben Murdoch014dc512016-03-22 12:00:34 +000025 PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, Handle<Map> map,
26 Handle<JSObject> holder, CacheHolderFlag cache_holder)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027 : PropertyAccessCompiler(isolate, kind, cache_holder),
Ben Murdoch014dc512016-03-22 12:00:34 +000028 map_(map),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029 holder_(holder) {}
30
31 virtual ~PropertyHandlerCompiler() {}
32
33 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Ben Murdoch014dc512016-03-22 12:00:34 +000034 Label* miss, ReturnHolder return_what) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035 UNREACHABLE();
36 return receiver();
37 }
38
39 virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
40
Emily Bernier958fae72015-03-24 16:35:39 -040041 // Frontend loads from receiver(), returns holder register which may be
42 // different.
43 Register Frontend(Handle<Name> name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 void NonexistentFrontendHeader(Handle<Name> name, Label* miss,
45 Register scratch1, Register scratch2);
46
Emily Bernier958fae72015-03-24 16:35:39 -040047 // When FLAG_vector_ics is true, handlers that have the possibility of missing
48 // will need to save and pass these to miss handlers.
49 void PushVectorAndSlot() { PushVectorAndSlot(vector(), slot()); }
50 void PushVectorAndSlot(Register vector, Register slot);
51 void PopVectorAndSlot() { PopVectorAndSlot(vector(), slot()); }
52 void PopVectorAndSlot(Register vector, Register slot);
53
54 void DiscardVectorAndSlot();
55
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056 // TODO(verwaest): Make non-static.
Ben Murdoch014dc512016-03-22 12:00:34 +000057 static void GenerateApiAccessorCall(MacroAssembler* masm,
58 const CallOptimization& optimization,
59 Handle<Map> receiver_map,
60 Register receiver, Register scratch,
61 bool is_store, Register store_parameter,
62 Register accessor_holder,
63 int accessor_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000064
65 // Helper function used to check that the dictionary doesn't contain
66 // the property. This function may return false negatives, so miss_label
67 // must always call a backup property check that is complete.
68 // This function is safe to call if the receiver has fast properties.
69 // Name must be unique and receiver must be a heap object.
70 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
71 Label* miss_label,
72 Register receiver,
73 Handle<Name> name, Register r0,
74 Register r1);
75
76 // Generate code to check that a global property cell is empty. Create
77 // the property cell at compilation time if no cell exists for the
78 // property.
79 static void GenerateCheckPropertyCell(MacroAssembler* masm,
80 Handle<JSGlobalObject> global,
81 Handle<Name> name, Register scratch,
82 Label* miss);
83
84 // Generates code that verifies that the property holder has not changed
85 // (checking maps of objects in the prototype chain for fast and global
86 // objects or doing negative lookup for slow objects, ensures that the
87 // property cells for global objects are still empty) and checks that the map
88 // of the holder has not changed. If necessary the function also generates
89 // code for security check in case of global object holders. Helps to make
90 // sure that the current IC is still valid.
91 //
92 // The scratch and holder registers are always clobbered, but the object
93 // register is only clobbered if it the same as the holder register. The
94 // function returns a register containing the holder - either object_reg or
95 // holder_reg.
96 Register CheckPrototypes(Register object_reg, Register holder_reg,
97 Register scratch1, Register scratch2,
98 Handle<Name> name, Label* miss,
Ben Murdoch014dc512016-03-22 12:00:34 +000099 PrototypeCheckType check, ReturnHolder return_what);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100101 Handle<Code> GetCode(Code::Kind kind, Handle<Name> name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 void set_holder(Handle<JSObject> holder) { holder_ = holder; }
Ben Murdoch014dc512016-03-22 12:00:34 +0000103 Handle<Map> map() const { return map_; }
104 void set_map(Handle<Map> map) { map_ = map; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 Handle<JSObject> holder() const { return holder_; }
106
107 private:
Ben Murdoch014dc512016-03-22 12:00:34 +0000108 Handle<Map> map_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 Handle<JSObject> holder_;
110};
111
112
113class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
114 public:
Ben Murdoch014dc512016-03-22 12:00:34 +0000115 NamedLoadHandlerCompiler(Isolate* isolate, Handle<Map> map,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116 Handle<JSObject> holder,
117 CacheHolderFlag cache_holder)
Ben Murdoch014dc512016-03-22 12:00:34 +0000118 : PropertyHandlerCompiler(isolate, Code::LOAD_IC, map, holder,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119 cache_holder) {}
120
121 virtual ~NamedLoadHandlerCompiler() {}
122
123 Handle<Code> CompileLoadField(Handle<Name> name, FieldIndex index);
124
125 Handle<Code> CompileLoadCallback(Handle<Name> name,
Ben Murdochf91f0612016-11-29 16:50:11 +0000126 Handle<AccessorInfo> callback,
127 Handle<Code> slow_stub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128
129 Handle<Code> CompileLoadCallback(Handle<Name> name,
Ben Murdoch014dc512016-03-22 12:00:34 +0000130 const CallOptimization& call_optimization,
Ben Murdochf91f0612016-11-29 16:50:11 +0000131 int accessor_index, Handle<Code> slow_stub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132
133 Handle<Code> CompileLoadConstant(Handle<Name> name, int constant_index);
134
135 // The LookupIterator is used to perform a lookup behind the interceptor. If
136 // the iterator points to a LookupIterator::PROPERTY, its access will be
137 // inlined.
138 Handle<Code> CompileLoadInterceptor(LookupIterator* it);
139
Ben Murdoch014dc512016-03-22 12:00:34 +0000140 Handle<Code> CompileLoadViaGetter(Handle<Name> name, int accessor_index,
141 int expected_arguments);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000142
143 Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
144 bool is_configurable);
145
146 // Static interface
147 static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
Ben Murdoch014dc512016-03-22 12:00:34 +0000148 Handle<Map> map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149
Ben Murdoch014dc512016-03-22 12:00:34 +0000150 static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
151 Register receiver, Register holder,
152 int accessor_index, int expected_arguments,
153 Register scratch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154
155 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000156 GenerateLoadViaGetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
157 no_reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 }
159
160 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
161 Register receiver,
162 Register scratch1,
163 Register scratch2,
164 Label* miss_label);
165
166 // These constants describe the structure of the interceptor arguments on the
167 // stack. The arguments are pushed by the (platform-specific)
168 // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
169 // LoadWithInterceptor.
170 static const int kInterceptorArgsNameIndex = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000171 static const int kInterceptorArgsThisIndex = 1;
172 static const int kInterceptorArgsHolderIndex = 2;
173 static const int kInterceptorArgsLength = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174
175 protected:
176 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Ben Murdoch014dc512016-03-22 12:00:34 +0000177 Label* miss, ReturnHolder return_what);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178
179 virtual void FrontendFooter(Handle<Name> name, Label* miss);
180
181 private:
182 Handle<Code> CompileLoadNonexistent(Handle<Name> name);
183 void GenerateLoadConstant(Handle<Object> value);
Ben Murdoch109988c2016-05-18 11:27:45 +0100184 void GenerateLoadCallback(Register reg, Handle<AccessorInfo> callback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 void GenerateLoadCallback(const CallOptimization& call_optimization,
186 Handle<Map> receiver_map);
Emily Bernier958fae72015-03-24 16:35:39 -0400187
188 // Helper emits no code if vector-ics are disabled.
189 void InterceptorVectorSlotPush(Register holder_reg);
190 enum PopMode { POP, DISCARD };
191 void InterceptorVectorSlotPop(Register holder_reg, PopMode mode = POP);
192
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 void GenerateLoadInterceptor(Register holder_reg);
194 void GenerateLoadInterceptorWithFollowup(LookupIterator* it,
195 Register holder_reg);
196 void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
197
198 // Generates prototype loading code that uses the objects from the
199 // context we were in when this function was called. If the context
200 // has changed, a jump to miss is performed. This ties the generated
201 // code to a particular context and so must not be used in cases
202 // where the generated code is not allowed to have references to
203 // objects from a context.
204 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
205 int index,
206 Register prototype,
207 Label* miss);
208
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100209 Register scratch3() { return registers_[4]; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210};
211
212
213class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
214 public:
Ben Murdoch014dc512016-03-22 12:00:34 +0000215 explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 Handle<JSObject> holder)
Ben Murdoch014dc512016-03-22 12:00:34 +0000217 : PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 kCacheOnReceiver) {}
219
220 virtual ~NamedStoreHandlerCompiler() {}
221
222 Handle<Code> CompileStoreTransition(Handle<Map> transition,
223 Handle<Name> name);
224 Handle<Code> CompileStoreField(LookupIterator* it);
225 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
Ben Murdoch109988c2016-05-18 11:27:45 +0100226 Handle<AccessorInfo> callback,
227 LanguageMode language_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
Ben Murdoch014dc512016-03-22 12:00:34 +0000229 const CallOptimization& call_optimization,
Ben Murdochf91f0612016-11-29 16:50:11 +0000230 int accessor_index, Handle<Code> slow_stub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
Ben Murdoch014dc512016-03-22 12:00:34 +0000232 int accessor_index,
233 int expected_arguments);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234
Ben Murdoch014dc512016-03-22 12:00:34 +0000235 static void GenerateStoreViaSetter(MacroAssembler* masm, Handle<Map> map,
236 Register receiver, Register holder,
237 int accessor_index, int expected_arguments,
238 Register scratch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239
240 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000241 GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
242 no_reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 }
244
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 protected:
246 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Ben Murdoch014dc512016-03-22 12:00:34 +0000247 Label* miss, ReturnHolder return_what);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248
249 virtual void FrontendFooter(Handle<Name> name, Label* miss);
250 void GenerateRestoreName(Label* label, Handle<Name> name);
251
Ben Murdoch014dc512016-03-22 12:00:34 +0000252 // Pop the vector and slot into appropriate registers, moving the map in
253 // the process. (This is an accomodation for register pressure on ia32).
254 void RearrangeVectorAndSlot(Register current_map, Register destination_map);
255
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256 private:
Emily Bernier958fae72015-03-24 16:35:39 -0400257 void GenerateRestoreName(Handle<Name> name);
Ben Murdoch014dc512016-03-22 12:00:34 +0000258 void GenerateRestoreMap(Handle<Map> transition, Register map_reg,
259 Register scratch, Label* miss);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260
Emily Bernier958fae72015-03-24 16:35:39 -0400261 void GenerateConstantCheck(Register map_reg, int descriptor,
262 Register value_reg, Register scratch,
263 Label* miss_label);
264
Ben Murdoch109988c2016-05-18 11:27:45 +0100265 bool RequiresFieldTypeChecks(FieldType* field_type) const;
266 void GenerateFieldTypeChecks(FieldType* field_type, Register value_reg,
Emily Bernier958fae72015-03-24 16:35:39 -0400267 Label* miss_label);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 static Register value();
270};
271
272
273class ElementHandlerCompiler : public PropertyHandlerCompiler {
274 public:
275 explicit ElementHandlerCompiler(Isolate* isolate)
276 : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
Ben Murdoch014dc512016-03-22 12:00:34 +0000277 Handle<Map>::null(), Handle<JSObject>::null(),
278 kCacheOnReceiver) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279
280 virtual ~ElementHandlerCompiler() {}
281
Ben Murdochf91f0612016-11-29 16:50:11 +0000282 static Handle<Object> GetKeyedLoadHandler(Handle<Map> receiver_map,
283 Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 void CompileElementHandlers(MapHandleList* receiver_maps,
Ben Murdochf91f0612016-11-29 16:50:11 +0000285 List<Handle<Object>>* handlers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286
287 static void GenerateStoreSlow(MacroAssembler* masm);
288};
Ben Murdoch014dc512016-03-22 12:00:34 +0000289} // namespace internal
290} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291
292#endif // V8_IC_HANDLER_COMPILER_H_