1 // Copyright 2016 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 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h"
7 #include "src/code-stub-assembler.h"
8 #include "src/ic/handler-compiler.h"
9 #include "src/ic/ic.h"
10 #include "src/ic/keyed-store-generic.h"
11 #include "src/objects-inl.h"
12
13 namespace v8 {
14 namespace internal {
15
TF_BUILTIN(KeyedLoadIC_IndexedString,CodeStubAssembler)16 TF_BUILTIN(KeyedLoadIC_IndexedString, CodeStubAssembler) {
17 typedef LoadWithVectorDescriptor Descriptor;
18
19 Node* receiver = Parameter(Descriptor::kReceiver);
20 Node* index = Parameter(Descriptor::kName);
21 Node* slot = Parameter(Descriptor::kSlot);
22 Node* vector = Parameter(Descriptor::kVector);
23 Node* context = Parameter(Descriptor::kContext);
24
25 Label miss(this);
26
27 Node* index_intptr = TryToIntptr(index, &miss);
28 Node* length = SmiUntag(LoadStringLength(receiver));
29 GotoIf(UintPtrGreaterThanOrEqual(index_intptr, length), &miss);
30
31 Node* code = StringCharCodeAt(receiver, index_intptr, INTPTR_PARAMETERS);
32 Node* result = StringFromCharCode(code);
33 Return(result);
34
35 Bind(&miss);
36 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, index, slot,
37 vector);
38 }
39
TF_BUILTIN(KeyedLoadIC_Miss,CodeStubAssembler)40 TF_BUILTIN(KeyedLoadIC_Miss, CodeStubAssembler) {
41 typedef LoadWithVectorDescriptor Descriptor;
42
43 Node* receiver = Parameter(Descriptor::kReceiver);
44 Node* name = Parameter(Descriptor::kName);
45 Node* slot = Parameter(Descriptor::kSlot);
46 Node* vector = Parameter(Descriptor::kVector);
47 Node* context = Parameter(Descriptor::kContext);
48
49 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, name, slot,
50 vector);
51 }
52
TF_BUILTIN(KeyedLoadIC_Slow,CodeStubAssembler)53 TF_BUILTIN(KeyedLoadIC_Slow, CodeStubAssembler) {
54 typedef LoadWithVectorDescriptor Descriptor;
55
56 Node* receiver = Parameter(Descriptor::kReceiver);
57 Node* name = Parameter(Descriptor::kName);
58 Node* context = Parameter(Descriptor::kContext);
59
60 TailCallRuntime(Runtime::kKeyedGetProperty, context, receiver, name);
61 }
62
Generate_KeyedStoreIC_Megamorphic(compiler::CodeAssemblerState * state)63 void Builtins::Generate_KeyedStoreIC_Megamorphic(
64 compiler::CodeAssemblerState* state) {
65 KeyedStoreGenericGenerator::Generate(state, SLOPPY);
66 }
67
Generate_KeyedStoreIC_Megamorphic_Strict(compiler::CodeAssemblerState * state)68 void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict(
69 compiler::CodeAssemblerState* state) {
70 KeyedStoreGenericGenerator::Generate(state, STRICT);
71 }
72
TF_BUILTIN(KeyedStoreIC_Miss,CodeStubAssembler)73 TF_BUILTIN(KeyedStoreIC_Miss, CodeStubAssembler) {
74 typedef StoreWithVectorDescriptor Descriptor;
75
76 Node* receiver = Parameter(Descriptor::kReceiver);
77 Node* name = Parameter(Descriptor::kName);
78 Node* value = Parameter(Descriptor::kValue);
79 Node* slot = Parameter(Descriptor::kSlot);
80 Node* vector = Parameter(Descriptor::kVector);
81 Node* context = Parameter(Descriptor::kContext);
82
83 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
84 receiver, name);
85 }
86
TF_BUILTIN(KeyedStoreIC_Slow,CodeStubAssembler)87 TF_BUILTIN(KeyedStoreIC_Slow, CodeStubAssembler) {
88 typedef StoreWithVectorDescriptor Descriptor;
89
90 Node* receiver = Parameter(Descriptor::kReceiver);
91 Node* name = Parameter(Descriptor::kName);
92 Node* value = Parameter(Descriptor::kValue);
93 Node* slot = Parameter(Descriptor::kSlot);
94 Node* vector = Parameter(Descriptor::kVector);
95 Node* context = Parameter(Descriptor::kContext);
96
97 // The slow case calls into the runtime to complete the store without causing
98 // an IC miss that would otherwise cause a transition to the generic stub.
99 TailCallRuntime(Runtime::kKeyedStoreIC_Slow, context, value, slot, vector,
100 receiver, name);
101 }
102
TF_BUILTIN(LoadGlobalIC_Miss,CodeStubAssembler)103 TF_BUILTIN(LoadGlobalIC_Miss, CodeStubAssembler) {
104 typedef LoadGlobalWithVectorDescriptor Descriptor;
105
106 Node* name = Parameter(Descriptor::kName);
107 Node* slot = Parameter(Descriptor::kSlot);
108 Node* vector = Parameter(Descriptor::kVector);
109 Node* context = Parameter(Descriptor::kContext);
110
111 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, name, slot, vector);
112 }
113
TF_BUILTIN(LoadGlobalIC_Slow,CodeStubAssembler)114 TF_BUILTIN(LoadGlobalIC_Slow, CodeStubAssembler) {
115 typedef LoadGlobalWithVectorDescriptor Descriptor;
116
117 Node* name = Parameter(Descriptor::kName);
118 Node* slot = Parameter(Descriptor::kSlot);
119 Node* vector = Parameter(Descriptor::kVector);
120 Node* context = Parameter(Descriptor::kContext);
121
122 TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, name, slot, vector);
123 }
124
Generate_LoadIC_Getter_ForDeopt(MacroAssembler * masm)125 void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
126 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
127 }
128
TF_BUILTIN(LoadIC_FunctionPrototype,CodeStubAssembler)129 TF_BUILTIN(LoadIC_FunctionPrototype, CodeStubAssembler) {
130 typedef LoadWithVectorDescriptor Descriptor;
131
132 Node* receiver = Parameter(Descriptor::kReceiver);
133 Node* name = Parameter(Descriptor::kName);
134 Node* slot = Parameter(Descriptor::kSlot);
135 Node* vector = Parameter(Descriptor::kVector);
136 Node* context = Parameter(Descriptor::kContext);
137
138 Label miss(this);
139
140 Node* proto_or_map =
141 LoadObjectField(receiver, JSFunction::kPrototypeOrInitialMapOffset);
142 GotoIf(IsTheHole(proto_or_map), &miss);
143
144 Variable var_result(this, MachineRepresentation::kTagged, proto_or_map);
145 Label done(this, &var_result);
146 GotoIfNot(IsMap(proto_or_map), &done);
147
148 var_result.Bind(LoadMapPrototype(proto_or_map));
149 Goto(&done);
150
151 Bind(&done);
152 Return(var_result.value());
153
154 Bind(&miss);
155 TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector);
156 }
157
TF_BUILTIN(LoadIC_Miss,CodeStubAssembler)158 TF_BUILTIN(LoadIC_Miss, CodeStubAssembler) {
159 typedef LoadWithVectorDescriptor Descriptor;
160
161 Node* receiver = Parameter(Descriptor::kReceiver);
162 Node* name = Parameter(Descriptor::kName);
163 Node* slot = Parameter(Descriptor::kSlot);
164 Node* vector = Parameter(Descriptor::kVector);
165 Node* context = Parameter(Descriptor::kContext);
166
167 TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector);
168 }
169
TF_BUILTIN(LoadIC_Normal,CodeStubAssembler)170 TF_BUILTIN(LoadIC_Normal, CodeStubAssembler) {
171 typedef LoadWithVectorDescriptor Descriptor;
172
173 Node* receiver = Parameter(Descriptor::kReceiver);
174 Node* name = Parameter(Descriptor::kName);
175 Node* context = Parameter(Descriptor::kContext);
176
177 Label slow(this);
178 {
179 Node* properties = LoadProperties(receiver);
180 Variable var_name_index(this, MachineType::PointerRepresentation());
181 Label found(this, &var_name_index);
182 NameDictionaryLookup<NameDictionary>(properties, name, &found,
183 &var_name_index, &slow);
184 Bind(&found);
185 {
186 Variable var_details(this, MachineRepresentation::kWord32);
187 Variable var_value(this, MachineRepresentation::kTagged);
188 LoadPropertyFromNameDictionary(properties, var_name_index.value(),
189 &var_details, &var_value);
190 Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
191 context, receiver, &slow);
192 Return(value);
193 }
194 }
195
196 Bind(&slow);
197 TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
198 }
199
TF_BUILTIN(LoadIC_Slow,CodeStubAssembler)200 TF_BUILTIN(LoadIC_Slow, CodeStubAssembler) {
201 typedef LoadWithVectorDescriptor Descriptor;
202
203 Node* receiver = Parameter(Descriptor::kReceiver);
204 Node* name = Parameter(Descriptor::kName);
205 Node* context = Parameter(Descriptor::kContext);
206
207 TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
208 }
209
TF_BUILTIN(StoreIC_Miss,CodeStubAssembler)210 TF_BUILTIN(StoreIC_Miss, CodeStubAssembler) {
211 typedef StoreWithVectorDescriptor Descriptor;
212
213 Node* receiver = Parameter(Descriptor::kReceiver);
214 Node* name = Parameter(Descriptor::kName);
215 Node* value = Parameter(Descriptor::kValue);
216 Node* slot = Parameter(Descriptor::kSlot);
217 Node* vector = Parameter(Descriptor::kVector);
218 Node* context = Parameter(Descriptor::kContext);
219
220 TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector,
221 receiver, name);
222 }
223
TF_BUILTIN(StoreIC_Normal,CodeStubAssembler)224 TF_BUILTIN(StoreIC_Normal, CodeStubAssembler) {
225 typedef StoreWithVectorDescriptor Descriptor;
226
227 Node* receiver = Parameter(Descriptor::kReceiver);
228 Node* name = Parameter(Descriptor::kName);
229 Node* value = Parameter(Descriptor::kValue);
230 Node* slot = Parameter(Descriptor::kSlot);
231 Node* vector = Parameter(Descriptor::kVector);
232 Node* context = Parameter(Descriptor::kContext);
233
234 Label slow(this);
235 {
236 Node* properties = LoadProperties(receiver);
237 Variable var_name_index(this, MachineType::PointerRepresentation());
238 Label found(this, &var_name_index);
239 NameDictionaryLookup<NameDictionary>(properties, name, &found,
240 &var_name_index, &slow);
241 Bind(&found);
242 {
243 Node* details = LoadDetailsByKeyIndex<NameDictionary>(
244 properties, var_name_index.value());
245 // Check that the property is a writable data property (no accessor).
246 const int kTypeAndReadOnlyMask = PropertyDetails::KindField::kMask |
247 PropertyDetails::kAttributesReadOnlyMask;
248 STATIC_ASSERT(kData == 0);
249 GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), &slow);
250 StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
251 value);
252 Return(value);
253 }
254 }
255
256 Bind(&slow);
257 TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector,
258 receiver, name);
259 }
260
Generate_StoreIC_Setter_ForDeopt(MacroAssembler * masm)261 void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
262 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
263 }
264
265 } // namespace internal
266 } // namespace v8
267