blob: a571f4f6bbbefc562f7f43f5a7c16a649c7fc60f [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 Murdoch4a90d5f2016-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 Murdochc5610432016-08-08 18:44:38 +010022 CacheHolderFlag cache_holder);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023
24 protected:
Ben Murdoch4a90d5f2016-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 Murdoch4a90d5f2016-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 Murdoch4a90d5f2016-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 Bernierd0a1eb72015-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 Bernierd0a1eb72015-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 Murdoch4a90d5f2016-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 Murdoch4a90d5f2016-03-22 12:00:34 +000099 PrototypeCheckType check, ReturnHolder return_what);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100
Ben Murdochc5610432016-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 Murdoch4a90d5f2016-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 Murdoch4a90d5f2016-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 Murdoch4a90d5f2016-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 Murdoch4a90d5f2016-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 Murdoch097c5b22016-05-18 11:27:45 +0100126 Handle<AccessorInfo> callback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127
128 Handle<Code> CompileLoadCallback(Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 const CallOptimization& call_optimization,
130 int accessor_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131
132 Handle<Code> CompileLoadConstant(Handle<Name> name, int constant_index);
133
134 // The LookupIterator is used to perform a lookup behind the interceptor. If
135 // the iterator points to a LookupIterator::PROPERTY, its access will be
136 // inlined.
137 Handle<Code> CompileLoadInterceptor(LookupIterator* it);
138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 Handle<Code> CompileLoadViaGetter(Handle<Name> name, int accessor_index,
140 int expected_arguments);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141
142 Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
143 bool is_configurable);
144
145 // Static interface
146 static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 Handle<Map> map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149 static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
150 Register receiver, Register holder,
151 int accessor_index, int expected_arguments,
152 Register scratch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153
154 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 GenerateLoadViaGetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
156 no_reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 }
158
159 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
160 Register receiver,
161 Register scratch1,
162 Register scratch2,
163 Label* miss_label);
164
165 // These constants describe the structure of the interceptor arguments on the
166 // stack. The arguments are pushed by the (platform-specific)
167 // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
168 // LoadWithInterceptor.
169 static const int kInterceptorArgsNameIndex = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 static const int kInterceptorArgsThisIndex = 1;
171 static const int kInterceptorArgsHolderIndex = 2;
172 static const int kInterceptorArgsLength = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173
174 protected:
175 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 Label* miss, ReturnHolder return_what);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177
178 virtual void FrontendFooter(Handle<Name> name, Label* miss);
179
180 private:
181 Handle<Code> CompileLoadNonexistent(Handle<Name> name);
182 void GenerateLoadConstant(Handle<Object> value);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100183 void GenerateLoadCallback(Register reg, Handle<AccessorInfo> callback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 void GenerateLoadCallback(const CallOptimization& call_optimization,
185 Handle<Map> receiver_map);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186
187 // Helper emits no code if vector-ics are disabled.
188 void InterceptorVectorSlotPush(Register holder_reg);
189 enum PopMode { POP, DISCARD };
190 void InterceptorVectorSlotPop(Register holder_reg, PopMode mode = POP);
191
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 void GenerateLoadInterceptor(Register holder_reg);
193 void GenerateLoadInterceptorWithFollowup(LookupIterator* it,
194 Register holder_reg);
195 void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
196
197 // Generates prototype loading code that uses the objects from the
198 // context we were in when this function was called. If the context
199 // has changed, a jump to miss is performed. This ties the generated
200 // code to a particular context and so must not be used in cases
201 // where the generated code is not allowed to have references to
202 // objects from a context.
203 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
204 int index,
205 Register prototype,
206 Label* miss);
207
Ben Murdoch61f157c2016-09-16 13:49:30 +0100208 Register scratch3() { return registers_[4]; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209};
210
211
212class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
213 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 Handle<JSObject> holder)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 : PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 kCacheOnReceiver) {}
218
219 virtual ~NamedStoreHandlerCompiler() {}
220
221 Handle<Code> CompileStoreTransition(Handle<Map> transition,
222 Handle<Name> name);
223 Handle<Code> CompileStoreField(LookupIterator* it);
224 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100225 Handle<AccessorInfo> callback,
226 LanguageMode language_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 const CallOptimization& call_optimization,
229 int accessor_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 int accessor_index,
232 int expected_arguments);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 static void GenerateStoreViaSetter(MacroAssembler* masm, Handle<Map> map,
235 Register receiver, Register holder,
236 int accessor_index, int expected_arguments,
237 Register scratch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238
239 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
241 no_reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 }
243
244 static void GenerateSlow(MacroAssembler* masm);
245
246 protected:
247 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 Label* miss, ReturnHolder return_what);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249
250 virtual void FrontendFooter(Handle<Name> name, Label* miss);
251 void GenerateRestoreName(Label* label, Handle<Name> name);
252
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 // Pop the vector and slot into appropriate registers, moving the map in
254 // the process. (This is an accomodation for register pressure on ia32).
255 void RearrangeVectorAndSlot(Register current_map, Register destination_map);
256
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400258 void GenerateRestoreName(Handle<Name> name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 void GenerateRestoreMap(Handle<Map> transition, Register map_reg,
260 Register scratch, Label* miss);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400262 void GenerateConstantCheck(Register map_reg, int descriptor,
263 Register value_reg, Register scratch,
264 Label* miss_label);
265
Ben Murdoch097c5b22016-05-18 11:27:45 +0100266 bool RequiresFieldTypeChecks(FieldType* field_type) const;
267 void GenerateFieldTypeChecks(FieldType* field_type, Register value_reg,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400268 Label* miss_label);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269
270 static Builtins::Name SlowBuiltin(Code::Kind kind) {
271 switch (kind) {
272 case Code::STORE_IC:
273 return Builtins::kStoreIC_Slow;
274 case Code::KEYED_STORE_IC:
275 return Builtins::kKeyedStoreIC_Slow;
276 default:
277 UNREACHABLE();
278 }
279 return Builtins::kStoreIC_Slow;
280 }
281
282 static Register value();
283};
284
285
286class ElementHandlerCompiler : public PropertyHandlerCompiler {
287 public:
288 explicit ElementHandlerCompiler(Isolate* isolate)
289 : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 Handle<Map>::null(), Handle<JSObject>::null(),
291 kCacheOnReceiver) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000292
293 virtual ~ElementHandlerCompiler() {}
294
295 void CompileElementHandlers(MapHandleList* receiver_maps,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100296 CodeHandleList* handlers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297
298 static void GenerateStoreSlow(MacroAssembler* masm);
299};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300} // namespace internal
301} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302
303#endif // V8_IC_HANDLER_COMPILER_H_