Line data Source code
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 : class PropertyHandlerCompiler : public PropertyAccessCompiler {
17 : public:
18 : static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind);
19 :
20 : protected:
21 : PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, Handle<Map> map,
22 : Handle<JSObject> holder)
23 38698 : : PropertyAccessCompiler(isolate, kind), map_(map), holder_(holder) {}
24 :
25 38698 : virtual ~PropertyHandlerCompiler() {}
26 :
27 0 : virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
28 : Label* miss) {
29 0 : UNREACHABLE();
30 : return receiver();
31 : }
32 :
33 0 : virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
34 :
35 : // Frontend loads from receiver(), returns holder register which may be
36 : // different.
37 : Register Frontend(Handle<Name> name);
38 :
39 : // When FLAG_vector_ics is true, handlers that have the possibility of missing
40 : // will need to save and pass these to miss handlers.
41 38698 : void PushVectorAndSlot() { PushVectorAndSlot(vector(), slot()); }
42 : void PushVectorAndSlot(Register vector, Register slot);
43 77340 : void PopVectorAndSlot() { PopVectorAndSlot(vector(), slot()); }
44 : void PopVectorAndSlot(Register vector, Register slot);
45 :
46 : void DiscardVectorAndSlot();
47 :
48 : // TODO(verwaest): Make non-static.
49 : static void GenerateApiAccessorCall(MacroAssembler* masm,
50 : const CallOptimization& optimization,
51 : Handle<Map> receiver_map,
52 : Register receiver, Register scratch,
53 : bool is_store, Register store_parameter,
54 : Register accessor_holder,
55 : int accessor_index);
56 :
57 : // Helper function used to check that the dictionary doesn't contain
58 : // the property. This function may return false negatives, so miss_label
59 : // must always call a backup property check that is complete.
60 : // This function is safe to call if the receiver has fast properties.
61 : // Name must be unique and receiver must be a heap object.
62 : static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
63 : Label* miss_label,
64 : Register receiver,
65 : Handle<Name> name, Register r0,
66 : Register r1);
67 :
68 : // Generate code to check that a global property cell is empty. Create
69 : // the property cell at compilation time if no cell exists for the
70 : // property.
71 : static void GenerateCheckPropertyCell(MacroAssembler* masm,
72 : Handle<JSGlobalObject> global,
73 : Handle<Name> name, Register scratch,
74 : Label* miss);
75 :
76 : // Generates check that current native context has the same access rights
77 : // as the given |native_context_cell|.
78 : // If |compare_native_contexts_only| is true then access check is considered
79 : // passed if the execution-time native context is equal to contents of
80 : // |native_context_cell|.
81 : // If |compare_native_contexts_only| is false then access check is considered
82 : // passed if the execution-time native context is equal to contents of
83 : // |native_context_cell| or security tokens of both contexts are equal.
84 : void GenerateAccessCheck(Handle<WeakCell> native_context_cell,
85 : Register scratch1, Register scratch2, Label* miss,
86 : bool compare_native_contexts_only);
87 :
88 : // Generates code that verifies that the property holder has not changed
89 : // (checking maps of objects in the prototype chain for fast and global
90 : // objects or doing negative lookup for slow objects, ensures that the
91 : // property cells for global objects are still empty) and checks that the map
92 : // of the holder has not changed. If necessary the function also generates
93 : // code for security check in case of global object holders. Helps to make
94 : // sure that the current IC is still valid.
95 : //
96 : // The scratch and holder registers are always clobbered, but the object
97 : // register is only clobbered if it the same as the holder register. The
98 : // function returns a register containing the holder - either object_reg or
99 : // holder_reg.
100 : Register CheckPrototypes(Register object_reg, Register holder_reg,
101 : Register scratch1, Register scratch2,
102 : Handle<Name> name, Label* miss);
103 :
104 : Handle<Code> GetCode(Code::Kind kind, Handle<Name> name);
105 : Handle<Map> map() const { return map_; }
106 : Handle<JSObject> holder() const { return holder_; }
107 :
108 : private:
109 : Handle<Map> map_;
110 : Handle<JSObject> holder_;
111 : };
112 :
113 :
114 : class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
115 : public:
116 : NamedLoadHandlerCompiler(Isolate* isolate, Handle<Map> map,
117 : Handle<JSObject> holder)
118 277 : : PropertyHandlerCompiler(isolate, Code::LOAD_IC, map, holder) {}
119 :
120 277 : virtual ~NamedLoadHandlerCompiler() {}
121 :
122 : Handle<Code> CompileLoadCallback(Handle<Name> name,
123 : const CallOptimization& call_optimization,
124 : int accessor_index, Handle<Code> slow_stub);
125 :
126 : static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm);
127 :
128 : protected:
129 : virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
130 : Label* miss);
131 :
132 : virtual void FrontendFooter(Handle<Name> name, Label* miss);
133 :
134 : private:
135 277 : Register scratch3() { return registers_[4]; }
136 : };
137 :
138 :
139 : class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
140 : public:
141 : // All store handlers use StoreWithVectorDescriptor calling convention.
142 : typedef StoreWithVectorDescriptor Descriptor;
143 :
144 : explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
145 : Handle<JSObject> holder)
146 38421 : : PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder) {
147 : #ifdef DEBUG
148 : if (Descriptor::kPassLastArgsOnStack) {
149 : ZapStackArgumentsRegisterAliases();
150 : }
151 : #endif
152 : }
153 :
154 38421 : virtual ~NamedStoreHandlerCompiler() {}
155 :
156 : void ZapStackArgumentsRegisterAliases();
157 :
158 : Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
159 : Handle<AccessorInfo> callback,
160 : LanguageMode language_mode);
161 : Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
162 : const CallOptimization& call_optimization,
163 : int accessor_index, Handle<Code> slow_stub);
164 : Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
165 : int accessor_index,
166 : int expected_arguments);
167 :
168 : static void GenerateStoreViaSetter(MacroAssembler* masm, Handle<Map> map,
169 : Register receiver, Register holder,
170 : int accessor_index, int expected_arguments,
171 : Register scratch);
172 :
173 43 : static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
174 : GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
175 43 : no_reg);
176 43 : }
177 :
178 : protected:
179 : virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
180 : Label* miss);
181 :
182 : virtual void FrontendFooter(Handle<Name> name, Label* miss);
183 : void GenerateRestoreName(Label* label, Handle<Name> name);
184 :
185 : private:
186 : static Register value();
187 : };
188 :
189 : } // namespace internal
190 : } // namespace v8
191 :
192 : #endif // V8_IC_HANDLER_COMPILER_H_
|