• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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