OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ic/call-optimization.h" | 7 #include "src/ic/call-optimization.h" |
8 #include "src/ic/handler-compiler.h" | 8 #include "src/ic/handler-compiler.h" |
9 #include "src/ic/ic.h" | 9 #include "src/ic/ic.h" |
10 #include "src/ic/ic-inl.h" | 10 #include "src/ic/ic-inl.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 // Frontend for store uses the name register. It has to be restored before a | 122 // Frontend for store uses the name register. It has to be restored before a |
123 // miss. | 123 // miss. |
124 Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, | 124 Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, |
125 Handle<Name> name, | 125 Handle<Name> name, |
126 Label* miss) { | 126 Label* miss) { |
127 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, | 127 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, |
128 miss, SKIP_RECEIVER); | 128 miss, SKIP_RECEIVER); |
129 } | 129 } |
130 | 130 |
131 | 131 |
132 Register PropertyHandlerCompiler::Frontend(Register object_reg, | 132 Register PropertyHandlerCompiler::Frontend(Handle<Name> name) { |
133 Handle<Name> name) { | |
134 Label miss; | 133 Label miss; |
135 Register reg = FrontendHeader(object_reg, name, &miss); | 134 if (IC::ICUseVector(kind())) { |
| 135 PushVectorAndSlot(); |
| 136 } |
| 137 Register reg = FrontendHeader(receiver(), name, &miss); |
136 FrontendFooter(name, &miss); | 138 FrontendFooter(name, &miss); |
| 139 // The footer consumes the vector and slot from the stack if miss occurs. |
| 140 if (IC::ICUseVector(kind())) { |
| 141 DiscardVectorAndSlot(); |
| 142 } |
137 return reg; | 143 return reg; |
138 } | 144 } |
139 | 145 |
140 | 146 |
141 void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, | 147 void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, |
142 Label* miss, | 148 Label* miss, |
143 Register scratch1, | 149 Register scratch1, |
144 Register scratch2) { | 150 Register scratch2) { |
145 Register holder_reg; | 151 Register holder_reg; |
146 Handle<Map> last_map; | 152 Handle<Map> last_map; |
(...skipping 25 matching lines...) Expand all Loading... |
172 NameDictionary::kNotFound); | 178 NameDictionary::kNotFound); |
173 GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1, | 179 GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1, |
174 scratch2); | 180 scratch2); |
175 } | 181 } |
176 } | 182 } |
177 } | 183 } |
178 | 184 |
179 | 185 |
180 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, | 186 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, |
181 FieldIndex field) { | 187 FieldIndex field) { |
182 Register reg = Frontend(receiver(), name); | 188 Register reg = Frontend(name); |
183 __ Move(receiver(), reg); | 189 __ Move(receiver(), reg); |
184 LoadFieldStub stub(isolate(), field); | 190 LoadFieldStub stub(isolate(), field); |
185 GenerateTailCall(masm(), stub.GetCode()); | 191 GenerateTailCall(masm(), stub.GetCode()); |
186 return GetCode(kind(), Code::FAST, name); | 192 return GetCode(kind(), Code::FAST, name); |
187 } | 193 } |
188 | 194 |
189 | 195 |
190 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, | 196 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, |
191 int constant_index) { | 197 int constant_index) { |
192 Register reg = Frontend(receiver(), name); | 198 Register reg = Frontend(name); |
193 __ Move(receiver(), reg); | 199 __ Move(receiver(), reg); |
194 LoadConstantStub stub(isolate(), constant_index); | 200 LoadConstantStub stub(isolate(), constant_index); |
195 GenerateTailCall(masm(), stub.GetCode()); | 201 GenerateTailCall(masm(), stub.GetCode()); |
196 return GetCode(kind(), Code::FAST, name); | 202 return GetCode(kind(), Code::FAST, name); |
197 } | 203 } |
198 | 204 |
199 | 205 |
200 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 206 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
201 Handle<Name> name) { | 207 Handle<Name> name) { |
202 Label miss; | 208 Label miss; |
| 209 if (IC::ICUseVector(kind())) { |
| 210 DCHECK(kind() == Code::LOAD_IC); |
| 211 PushVectorAndSlot(); |
| 212 } |
203 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); | 213 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); |
| 214 if (IC::ICUseVector(kind())) { |
| 215 DiscardVectorAndSlot(); |
| 216 } |
204 GenerateLoadConstant(isolate()->factory()->undefined_value()); | 217 GenerateLoadConstant(isolate()->factory()->undefined_value()); |
205 FrontendFooter(name, &miss); | 218 FrontendFooter(name, &miss); |
206 return GetCode(kind(), Code::FAST, name); | 219 return GetCode(kind(), Code::FAST, name); |
207 } | 220 } |
208 | 221 |
209 | 222 |
210 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 223 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
211 Handle<Name> name, Handle<ExecutableAccessorInfo> callback) { | 224 Handle<Name> name, Handle<ExecutableAccessorInfo> callback) { |
212 Register reg = Frontend(receiver(), name); | 225 Register reg = Frontend(name); |
213 GenerateLoadCallback(reg, callback); | 226 GenerateLoadCallback(reg, callback); |
214 return GetCode(kind(), Code::FAST, name); | 227 return GetCode(kind(), Code::FAST, name); |
215 } | 228 } |
216 | 229 |
217 | 230 |
218 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 231 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
219 Handle<Name> name, const CallOptimization& call_optimization) { | 232 Handle<Name> name, const CallOptimization& call_optimization) { |
220 DCHECK(call_optimization.is_simple_api_call()); | 233 DCHECK(call_optimization.is_simple_api_call()); |
221 Frontend(receiver(), name); | 234 Frontend(name); |
222 Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); | 235 Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); |
223 GenerateFastApiCall(masm(), call_optimization, receiver_map, receiver(), | 236 GenerateFastApiCall(masm(), call_optimization, receiver_map, receiver(), |
224 scratch1(), false, 0, NULL); | 237 scratch1(), false, 0, NULL); |
225 return GetCode(kind(), Code::FAST, name); | 238 return GetCode(kind(), Code::FAST, name); |
226 } | 239 } |
227 | 240 |
228 | 241 |
| 242 void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { |
| 243 if (IC::ICUseVector(kind())) { |
| 244 if (holder_reg.is(receiver())) { |
| 245 PushVectorAndSlot(); |
| 246 } else { |
| 247 DCHECK(holder_reg.is(scratch1())); |
| 248 PushVectorAndSlot(scratch2(), scratch3()); |
| 249 } |
| 250 } |
| 251 } |
| 252 |
| 253 |
| 254 void NamedLoadHandlerCompiler::InterceptorVectorSlotPop(Register holder_reg, |
| 255 PopMode mode) { |
| 256 if (IC::ICUseVector(kind())) { |
| 257 if (mode == DISCARD) { |
| 258 DiscardVectorAndSlot(); |
| 259 } else { |
| 260 if (holder_reg.is(receiver())) { |
| 261 PopVectorAndSlot(); |
| 262 } else { |
| 263 DCHECK(holder_reg.is(scratch1())); |
| 264 PopVectorAndSlot(scratch2(), scratch3()); |
| 265 } |
| 266 } |
| 267 } |
| 268 } |
| 269 |
| 270 |
229 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( | 271 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( |
230 LookupIterator* it) { | 272 LookupIterator* it) { |
231 // So far the most popular follow ups for interceptor loads are FIELD and | 273 // So far the most popular follow ups for interceptor loads are FIELD and |
232 // ExecutableAccessorInfo, so inline only them. Other cases may be added | 274 // ExecutableAccessorInfo, so inline only them. Other cases may be added |
233 // later. | 275 // later. |
234 bool inline_followup = false; | 276 bool inline_followup = false; |
235 switch (it->state()) { | 277 switch (it->state()) { |
236 case LookupIterator::TRANSITION: | 278 case LookupIterator::TRANSITION: |
237 UNREACHABLE(); | 279 UNREACHABLE(); |
238 case LookupIterator::ACCESS_CHECK: | 280 case LookupIterator::ACCESS_CHECK: |
(...skipping 10 matching lines...) Expand all Loading... |
249 inline_followup = accessors->IsExecutableAccessorInfo(); | 291 inline_followup = accessors->IsExecutableAccessorInfo(); |
250 if (!inline_followup) break; | 292 if (!inline_followup) break; |
251 Handle<ExecutableAccessorInfo> info = | 293 Handle<ExecutableAccessorInfo> info = |
252 Handle<ExecutableAccessorInfo>::cast(accessors); | 294 Handle<ExecutableAccessorInfo>::cast(accessors); |
253 inline_followup = info->getter() != NULL && | 295 inline_followup = info->getter() != NULL && |
254 ExecutableAccessorInfo::IsCompatibleReceiverType( | 296 ExecutableAccessorInfo::IsCompatibleReceiverType( |
255 isolate(), info, type()); | 297 isolate(), info, type()); |
256 } | 298 } |
257 } | 299 } |
258 | 300 |
259 Register reg = Frontend(receiver(), it->name()); | 301 Label miss; |
| 302 InterceptorVectorSlotPush(receiver()); |
| 303 Register reg = FrontendHeader(receiver(), it->name(), &miss); |
| 304 FrontendFooter(it->name(), &miss); |
| 305 InterceptorVectorSlotPop(reg); |
| 306 |
260 if (inline_followup) { | 307 if (inline_followup) { |
261 // TODO(368): Compile in the whole chain: all the interceptors in | 308 // TODO(368): Compile in the whole chain: all the interceptors in |
262 // prototypes and ultimate answer. | 309 // prototypes and ultimate answer. |
263 GenerateLoadInterceptorWithFollowup(it, reg); | 310 GenerateLoadInterceptorWithFollowup(it, reg); |
264 } else { | 311 } else { |
265 GenerateLoadInterceptor(reg); | 312 GenerateLoadInterceptor(reg); |
266 } | 313 } |
267 return GetCode(kind(), Code::FAST, it->name()); | 314 return GetCode(kind(), Code::FAST, it->name()); |
268 } | 315 } |
269 | 316 |
270 | 317 |
271 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( | 318 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( |
272 LookupIterator* it, Register interceptor_reg) { | 319 LookupIterator* it, Register interceptor_reg) { |
273 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); | 320 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); |
274 | 321 |
275 set_type_for_object(holder()); | 322 set_type_for_object(holder()); |
276 set_holder(real_named_property_holder); | 323 set_holder(real_named_property_holder); |
277 Register reg = Frontend(interceptor_reg, it->name()); | 324 |
| 325 Label miss; |
| 326 InterceptorVectorSlotPush(interceptor_reg); |
| 327 Register reg = FrontendHeader(interceptor_reg, it->name(), &miss); |
| 328 FrontendFooter(it->name(), &miss); |
| 329 // We discard the vector and slot now because we don't miss below this point. |
| 330 InterceptorVectorSlotPop(reg, DISCARD); |
278 | 331 |
279 switch (it->state()) { | 332 switch (it->state()) { |
280 case LookupIterator::ACCESS_CHECK: | 333 case LookupIterator::ACCESS_CHECK: |
281 case LookupIterator::INTERCEPTOR: | 334 case LookupIterator::INTERCEPTOR: |
282 case LookupIterator::JSPROXY: | 335 case LookupIterator::JSPROXY: |
283 case LookupIterator::NOT_FOUND: | 336 case LookupIterator::NOT_FOUND: |
284 case LookupIterator::TRANSITION: | 337 case LookupIterator::TRANSITION: |
285 UNREACHABLE(); | 338 UNREACHABLE(); |
286 case LookupIterator::DATA: { | 339 case LookupIterator::DATA: { |
287 DCHECK_EQ(FIELD, it->property_details().type()); | 340 DCHECK_EQ(FIELD, it->property_details().type()); |
288 __ Move(receiver(), reg); | 341 __ Move(receiver(), reg); |
289 LoadFieldStub stub(isolate(), it->GetFieldIndex()); | 342 LoadFieldStub stub(isolate(), it->GetFieldIndex()); |
290 GenerateTailCall(masm(), stub.GetCode()); | 343 GenerateTailCall(masm(), stub.GetCode()); |
291 break; | 344 break; |
292 } | 345 } |
293 case LookupIterator::ACCESSOR: | 346 case LookupIterator::ACCESSOR: |
294 Handle<ExecutableAccessorInfo> info = | 347 Handle<ExecutableAccessorInfo> info = |
295 Handle<ExecutableAccessorInfo>::cast(it->GetAccessors()); | 348 Handle<ExecutableAccessorInfo>::cast(it->GetAccessors()); |
296 DCHECK_NE(NULL, info->getter()); | 349 DCHECK_NE(NULL, info->getter()); |
297 GenerateLoadCallback(reg, info); | 350 GenerateLoadCallback(reg, info); |
298 } | 351 } |
299 } | 352 } |
300 | 353 |
301 | 354 |
302 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( | 355 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( |
303 Handle<Name> name, Handle<JSFunction> getter) { | 356 Handle<Name> name, Handle<JSFunction> getter) { |
304 Frontend(receiver(), name); | 357 Frontend(name); |
305 GenerateLoadViaGetter(masm(), type(), receiver(), getter); | 358 GenerateLoadViaGetter(masm(), type(), receiver(), getter); |
306 return GetCode(kind(), Code::FAST, name); | 359 return GetCode(kind(), Code::FAST, name); |
307 } | 360 } |
308 | 361 |
309 | 362 |
310 // TODO(verwaest): Cleanup. holder() is actually the receiver. | 363 // TODO(verwaest): Cleanup. holder() is actually the receiver. |
311 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( | 364 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
312 Handle<Map> transition, Handle<Name> name) { | 365 Handle<Map> transition, Handle<Name> name) { |
313 Label miss; | 366 Label miss; |
314 | 367 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 GenerateTailCall(masm(), stub.GetCode()); | 435 GenerateTailCall(masm(), stub.GetCode()); |
383 | 436 |
384 __ bind(&miss); | 437 __ bind(&miss); |
385 TailCallBuiltin(masm(), MissBuiltin(kind())); | 438 TailCallBuiltin(masm(), MissBuiltin(kind())); |
386 return GetCode(kind(), Code::FAST, it->name()); | 439 return GetCode(kind(), Code::FAST, it->name()); |
387 } | 440 } |
388 | 441 |
389 | 442 |
390 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( | 443 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
391 Handle<JSObject> object, Handle<Name> name, Handle<JSFunction> setter) { | 444 Handle<JSObject> object, Handle<Name> name, Handle<JSFunction> setter) { |
392 Frontend(receiver(), name); | 445 Frontend(name); |
393 GenerateStoreViaSetter(masm(), type(), receiver(), setter); | 446 GenerateStoreViaSetter(masm(), type(), receiver(), setter); |
394 | 447 |
395 return GetCode(kind(), Code::FAST, name); | 448 return GetCode(kind(), Code::FAST, name); |
396 } | 449 } |
397 | 450 |
398 | 451 |
399 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 452 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
400 Handle<JSObject> object, Handle<Name> name, | 453 Handle<JSObject> object, Handle<Name> name, |
401 const CallOptimization& call_optimization) { | 454 const CallOptimization& call_optimization) { |
402 Frontend(receiver(), name); | 455 Frontend(name); |
403 Register values[] = {value()}; | 456 Register values[] = {value()}; |
404 GenerateFastApiCall(masm(), call_optimization, handle(object->map()), | 457 GenerateFastApiCall(masm(), call_optimization, handle(object->map()), |
405 receiver(), scratch1(), true, 1, values); | 458 receiver(), scratch1(), true, 1, values); |
406 return GetCode(kind(), Code::FAST, name); | 459 return GetCode(kind(), Code::FAST, name); |
407 } | 460 } |
408 | 461 |
409 | 462 |
410 #undef __ | 463 #undef __ |
411 | 464 |
412 | 465 |
(...skipping 23 matching lines...) Expand all Loading... |
436 DCHECK(elements_kind == DICTIONARY_ELEMENTS); | 489 DCHECK(elements_kind == DICTIONARY_ELEMENTS); |
437 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); | 490 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); |
438 } | 491 } |
439 } | 492 } |
440 | 493 |
441 handlers->Add(cached_stub); | 494 handlers->Add(cached_stub); |
442 } | 495 } |
443 } | 496 } |
444 } | 497 } |
445 } // namespace v8::internal | 498 } // namespace v8::internal |
OLD | NEW |