OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 // Decide whether the inline cache failed because of changes to the | 145 // Decide whether the inline cache failed because of changes to the |
146 // receiver itself or changes to one of its prototypes. | 146 // receiver itself or changes to one of its prototypes. |
147 // | 147 // |
148 // If there are changes to the receiver itself, the map of the | 148 // If there are changes to the receiver itself, the map of the |
149 // receiver will have changed and the current target will not be in | 149 // receiver will have changed and the current target will not be in |
150 // the receiver map's code cache. Therefore, if the current target | 150 // the receiver map's code cache. Therefore, if the current target |
151 // is in the receiver map's code cache, the inline cache failed due | 151 // is in the receiver map's code cache, the inline cache failed due |
152 // to prototype check failure. | 152 // to prototype check failure. |
153 int index = map->IndexInCodeCache(name, target); | 153 int index = map->IndexInCodeCache(name, target); |
154 if (index >= 0) { | 154 if (index >= 0) { |
155 // For keyed load/store, the most likely cause of cache failure is | 155 // For keyed load/store/call, the most likely cause of cache failure is |
156 // that the key has changed. We do not distinguish between | 156 // that the key has changed. We do not distinguish between |
157 // prototype and non-prototype failures for keyed access. | 157 // prototype and non-prototype failures for keyed access. |
158 Code::Kind kind = target->kind(); | 158 Code::Kind kind = target->kind(); |
159 if (kind == Code::KEYED_LOAD_IC || kind == Code::KEYED_STORE_IC) { | 159 if (kind == Code::KEYED_LOAD_IC || |
| 160 kind == Code::KEYED_STORE_IC || |
| 161 kind == Code::KEYED_CALL_IC) { |
160 return MONOMORPHIC; | 162 return MONOMORPHIC; |
161 } | 163 } |
162 | 164 |
163 // Remove the target from the code cache to avoid hitting the same | 165 // Remove the target from the code cache to avoid hitting the same |
164 // invalid stub again. | 166 // invalid stub again. |
165 map->RemoveFromCodeCache(String::cast(name), target, index); | 167 map->RemoveFromCodeCache(String::cast(name), target, index); |
166 | 168 |
167 return MONOMORPHIC_PROTOTYPE_FAILURE; | 169 return MONOMORPHIC_PROTOTYPE_FAILURE; |
168 } | 170 } |
169 | 171 |
(...skipping 19 matching lines...) Expand all Loading... |
189 RelocInfo* info = it.rinfo(); | 191 RelocInfo* info = it.rinfo(); |
190 if (info->pc() == addr) return info->rmode(); | 192 if (info->pc() == addr) return info->rmode(); |
191 } | 193 } |
192 UNREACHABLE(); | 194 UNREACHABLE(); |
193 return RelocInfo::NONE; | 195 return RelocInfo::NONE; |
194 } | 196 } |
195 | 197 |
196 | 198 |
197 Failure* IC::TypeError(const char* type, | 199 Failure* IC::TypeError(const char* type, |
198 Handle<Object> object, | 200 Handle<Object> object, |
199 Handle<String> name) { | 201 Handle<Object> key) { |
200 HandleScope scope; | 202 HandleScope scope; |
201 Handle<Object> args[2] = { name, object }; | 203 Handle<Object> args[2] = { key, object }; |
202 Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2)); | 204 Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2)); |
203 return Top::Throw(*error); | 205 return Top::Throw(*error); |
204 } | 206 } |
205 | 207 |
206 | 208 |
207 Failure* IC::ReferenceError(const char* type, Handle<String> name) { | 209 Failure* IC::ReferenceError(const char* type, Handle<String> name) { |
208 HandleScope scope; | 210 HandleScope scope; |
209 Handle<Object> error = | 211 Handle<Object> error = |
210 Factory::NewReferenceError(type, HandleVector(&name, 1)); | 212 Factory::NewReferenceError(type, HandleVector(&name, 1)); |
211 return Top::Throw(*error); | 213 return Top::Throw(*error); |
212 } | 214 } |
213 | 215 |
214 | 216 |
215 void IC::Clear(Address address) { | 217 void IC::Clear(Address address) { |
216 Code* target = GetTargetAtAddress(address); | 218 Code* target = GetTargetAtAddress(address); |
217 | 219 |
218 // Don't clear debug break inline cache as it will remove the break point. | 220 // Don't clear debug break inline cache as it will remove the break point. |
219 if (target->ic_state() == DEBUG_BREAK) return; | 221 if (target->ic_state() == DEBUG_BREAK) return; |
220 | 222 |
221 switch (target->kind()) { | 223 switch (target->kind()) { |
222 case Code::LOAD_IC: return LoadIC::Clear(address, target); | 224 case Code::LOAD_IC: return LoadIC::Clear(address, target); |
223 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); | 225 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); |
224 case Code::STORE_IC: return StoreIC::Clear(address, target); | 226 case Code::STORE_IC: return StoreIC::Clear(address, target); |
225 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); | 227 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); |
226 case Code::CALL_IC: return CallIC::Clear(address, target); | 228 case Code::CALL_IC: return CallIC::Clear(address, target); |
| 229 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target); |
227 case Code::BINARY_OP_IC: return; // Clearing these is tricky and does not | 230 case Code::BINARY_OP_IC: return; // Clearing these is tricky and does not |
228 // make any performance difference. | 231 // make any performance difference. |
229 default: UNREACHABLE(); | 232 default: UNREACHABLE(); |
230 } | 233 } |
231 } | 234 } |
232 | 235 |
233 | 236 |
234 void CallIC::Clear(Address address, Code* target) { | 237 void CallICBase::Clear(Address address, Code* target) { |
235 State state = target->ic_state(); | 238 State state = target->ic_state(); |
236 InLoopFlag in_loop = target->ic_in_loop(); | |
237 if (state == UNINITIALIZED) return; | 239 if (state == UNINITIALIZED) return; |
238 Code* code = | 240 Code* code = |
239 StubCache::FindCallInitialize(target->arguments_count(), in_loop); | 241 StubCache::FindCallInitialize(target->arguments_count(), |
| 242 target->ic_in_loop(), |
| 243 target->kind()); |
240 SetTargetAtAddress(address, code); | 244 SetTargetAtAddress(address, code); |
241 } | 245 } |
242 | 246 |
243 | 247 |
244 void KeyedLoadIC::Clear(Address address, Code* target) { | 248 void KeyedLoadIC::Clear(Address address, Code* target) { |
245 if (target->ic_state() == UNINITIALIZED) return; | 249 if (target->ic_state() == UNINITIALIZED) return; |
246 // Make sure to also clear the map used in inline fast cases. If we | 250 // Make sure to also clear the map used in inline fast cases. If we |
247 // do not clear these maps, cached code can keep objects alive | 251 // do not clear these maps, cached code can keep objects alive |
248 // through the embedded maps. | 252 // through the embedded maps. |
249 ClearInlinedVersion(address); | 253 ClearInlinedVersion(address); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 if (proto->IsNull()) { | 361 if (proto->IsNull()) { |
358 lookup->NotFound(); | 362 lookup->NotFound(); |
359 return; | 363 return; |
360 } | 364 } |
361 | 365 |
362 object = proto; | 366 object = proto; |
363 } | 367 } |
364 } | 368 } |
365 | 369 |
366 | 370 |
367 Object* CallIC::TryCallAsFunction(Object* object) { | 371 Object* CallICBase::TryCallAsFunction(Object* object) { |
368 HandleScope scope; | 372 HandleScope scope; |
369 Handle<Object> target(object); | 373 Handle<Object> target(object); |
370 Handle<Object> delegate = Execution::GetFunctionDelegate(target); | 374 Handle<Object> delegate = Execution::GetFunctionDelegate(target); |
371 | 375 |
372 if (delegate->IsJSFunction()) { | 376 if (delegate->IsJSFunction()) { |
373 // Patch the receiver and use the delegate as the function to | 377 // Patch the receiver and use the delegate as the function to |
374 // invoke. This is used for invoking objects as if they were | 378 // invoke. This is used for invoking objects as if they were |
375 // functions. | 379 // functions. |
376 const int argc = this->target()->arguments_count(); | 380 const int argc = this->target()->arguments_count(); |
377 StackFrameLocator locator; | 381 StackFrameLocator locator; |
378 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 382 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
379 int index = frame->ComputeExpressionsCount() - (argc + 1); | 383 int index = frame->ComputeExpressionsCount() - (argc + 1); |
380 frame->SetExpression(index, *target); | 384 frame->SetExpression(index, *target); |
381 } | 385 } |
382 | 386 |
383 return *delegate; | 387 return *delegate; |
384 } | 388 } |
385 | 389 |
386 void CallIC::ReceiverToObject(Handle<Object> object) { | 390 void CallICBase::ReceiverToObject(Handle<Object> object) { |
387 HandleScope scope; | 391 HandleScope scope; |
388 Handle<Object> receiver(object); | 392 Handle<Object> receiver(object); |
389 | 393 |
390 // Change the receiver to the result of calling ToObject on it. | 394 // Change the receiver to the result of calling ToObject on it. |
391 const int argc = this->target()->arguments_count(); | 395 const int argc = this->target()->arguments_count(); |
392 StackFrameLocator locator; | 396 StackFrameLocator locator; |
393 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 397 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
394 int index = frame->ComputeExpressionsCount() - (argc + 1); | 398 int index = frame->ComputeExpressionsCount() - (argc + 1); |
395 frame->SetExpression(index, *Factory::ToObject(object)); | 399 frame->SetExpression(index, *Factory::ToObject(object)); |
396 } | 400 } |
397 | 401 |
398 | 402 |
399 Object* CallIC::LoadFunction(State state, | 403 Object* CallICBase::LoadFunction(State state, |
400 Handle<Object> object, | 404 Handle<Object> object, |
401 Handle<String> name) { | 405 Handle<String> name) { |
402 // If the object is undefined or null it's illegal to try to get any | 406 // If the object is undefined or null it's illegal to try to get any |
403 // of its properties; throw a TypeError in that case. | 407 // of its properties; throw a TypeError in that case. |
404 if (object->IsUndefined() || object->IsNull()) { | 408 if (object->IsUndefined() || object->IsNull()) { |
405 return TypeError("non_object_property_call", object, name); | 409 return TypeError("non_object_property_call", object, name); |
406 } | 410 } |
407 | 411 |
408 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 412 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
409 ReceiverToObject(object); | 413 ReceiverToObject(object); |
410 } | 414 } |
411 | 415 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 return result; | 478 return result; |
475 } | 479 } |
476 | 480 |
477 // Try to find a suitable function delegate for the object at hand. | 481 // Try to find a suitable function delegate for the object at hand. |
478 result = TryCallAsFunction(result); | 482 result = TryCallAsFunction(result); |
479 return result->IsJSFunction() ? | 483 return result->IsJSFunction() ? |
480 result : TypeError("property_not_function", object, name); | 484 result : TypeError("property_not_function", object, name); |
481 } | 485 } |
482 | 486 |
483 | 487 |
484 void CallIC::UpdateCaches(LookupResult* lookup, | 488 void CallICBase::UpdateCaches(LookupResult* lookup, |
485 State state, | 489 State state, |
486 Handle<Object> object, | 490 Handle<Object> object, |
487 Handle<String> name) { | 491 Handle<String> name) { |
488 // Bail out if we didn't find a result. | 492 // Bail out if we didn't find a result. |
489 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 493 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
490 | 494 |
491 // Compute the number of arguments. | 495 // Compute the number of arguments. |
492 int argc = target()->arguments_count(); | 496 int argc = target()->arguments_count(); |
493 InLoopFlag in_loop = target()->ic_in_loop(); | 497 InLoopFlag in_loop = target()->ic_in_loop(); |
494 Object* code = NULL; | 498 Object* code = NULL; |
495 | 499 |
496 if (state == UNINITIALIZED) { | 500 if (state == UNINITIALIZED) { |
497 // This is the first time we execute this inline cache. | 501 // This is the first time we execute this inline cache. |
498 // Set the target to the pre monomorphic stub to delay | 502 // Set the target to the pre monomorphic stub to delay |
499 // setting the monomorphic state. | 503 // setting the monomorphic state. |
500 code = StubCache::ComputeCallPreMonomorphic(argc, in_loop); | 504 code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); |
501 } else if (state == MONOMORPHIC) { | 505 } else if (state == MONOMORPHIC) { |
502 code = StubCache::ComputeCallMegamorphic(argc, in_loop); | 506 code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); |
503 } else { | 507 } else { |
504 // Compute monomorphic stub. | 508 // Compute monomorphic stub. |
505 switch (lookup->type()) { | 509 switch (lookup->type()) { |
506 case FIELD: { | 510 case FIELD: { |
507 int index = lookup->GetFieldIndex(); | 511 int index = lookup->GetFieldIndex(); |
508 code = StubCache::ComputeCallField(argc, in_loop, *name, *object, | 512 code = StubCache::ComputeCallField(argc, |
509 lookup->holder(), index); | 513 in_loop, |
| 514 kind_, |
| 515 *name, |
| 516 *object, |
| 517 lookup->holder(), |
| 518 index); |
510 break; | 519 break; |
511 } | 520 } |
512 case CONSTANT_FUNCTION: { | 521 case CONSTANT_FUNCTION: { |
513 // Get the constant function and compute the code stub for this | 522 // Get the constant function and compute the code stub for this |
514 // call; used for rewriting to monomorphic state and making sure | 523 // call; used for rewriting to monomorphic state and making sure |
515 // that the code stub is in the stub cache. | 524 // that the code stub is in the stub cache. |
516 JSFunction* function = lookup->GetConstantFunction(); | 525 JSFunction* function = lookup->GetConstantFunction(); |
517 code = StubCache::ComputeCallConstant(argc, in_loop, *name, *object, | 526 code = StubCache::ComputeCallConstant(argc, |
518 lookup->holder(), function); | 527 in_loop, |
| 528 kind_, |
| 529 *name, |
| 530 *object, |
| 531 lookup->holder(), |
| 532 function); |
519 break; | 533 break; |
520 } | 534 } |
521 case NORMAL: { | 535 case NORMAL: { |
522 if (!object->IsJSObject()) return; | 536 if (!object->IsJSObject()) return; |
523 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 537 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
524 | 538 |
525 if (lookup->holder()->IsGlobalObject()) { | 539 if (lookup->holder()->IsGlobalObject()) { |
526 GlobalObject* global = GlobalObject::cast(lookup->holder()); | 540 GlobalObject* global = GlobalObject::cast(lookup->holder()); |
527 JSGlobalPropertyCell* cell = | 541 JSGlobalPropertyCell* cell = |
528 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 542 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); |
529 if (!cell->value()->IsJSFunction()) return; | 543 if (!cell->value()->IsJSFunction()) return; |
530 JSFunction* function = JSFunction::cast(cell->value()); | 544 JSFunction* function = JSFunction::cast(cell->value()); |
531 code = StubCache::ComputeCallGlobal(argc, | 545 code = StubCache::ComputeCallGlobal(argc, |
532 in_loop, | 546 in_loop, |
| 547 kind_, |
533 *name, | 548 *name, |
534 *receiver, | 549 *receiver, |
535 global, | 550 global, |
536 cell, | 551 cell, |
537 function); | 552 function); |
538 } else { | 553 } else { |
539 // There is only one shared stub for calling normalized | 554 // There is only one shared stub for calling normalized |
540 // properties. It does not traverse the prototype chain, so the | 555 // properties. It does not traverse the prototype chain, so the |
541 // property must be found in the receiver for the stub to be | 556 // property must be found in the receiver for the stub to be |
542 // applicable. | 557 // applicable. |
543 if (lookup->holder() != *receiver) return; | 558 if (lookup->holder() != *receiver) return; |
544 code = StubCache::ComputeCallNormal(argc, in_loop, *name, *receiver); | 559 code = StubCache::ComputeCallNormal(argc, |
| 560 in_loop, |
| 561 kind_, |
| 562 *name, |
| 563 *receiver); |
545 } | 564 } |
546 break; | 565 break; |
547 } | 566 } |
548 case INTERCEPTOR: { | 567 case INTERCEPTOR: { |
549 ASSERT(HasInterceptorGetter(lookup->holder())); | 568 ASSERT(HasInterceptorGetter(lookup->holder())); |
550 code = StubCache::ComputeCallInterceptor(argc, *name, *object, | 569 code = StubCache::ComputeCallInterceptor(argc, |
| 570 kind_, |
| 571 *name, |
| 572 *object, |
551 lookup->holder()); | 573 lookup->holder()); |
552 break; | 574 break; |
553 } | 575 } |
554 default: | 576 default: |
555 return; | 577 return; |
556 } | 578 } |
557 } | 579 } |
558 | 580 |
559 // If we're unable to compute the stub (not enough memory left), we | 581 // If we're unable to compute the stub (not enough memory left), we |
560 // simply avoid updating the caches. | 582 // simply avoid updating the caches. |
561 if (code == NULL || code->IsFailure()) return; | 583 if (code == NULL || code->IsFailure()) return; |
562 | 584 |
563 // Patch the call site depending on the state of the cache. | 585 // Patch the call site depending on the state of the cache. |
564 if (state == UNINITIALIZED || | 586 if (state == UNINITIALIZED || |
565 state == PREMONOMORPHIC || | 587 state == PREMONOMORPHIC || |
566 state == MONOMORPHIC || | 588 state == MONOMORPHIC || |
567 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 589 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
568 set_target(Code::cast(code)); | 590 set_target(Code::cast(code)); |
569 } | 591 } |
570 | 592 |
571 #ifdef DEBUG | 593 #ifdef DEBUG |
572 TraceIC("CallIC", name, state, target(), in_loop ? " (in-loop)" : ""); | 594 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
| 595 name, state, target(), in_loop ? " (in-loop)" : ""); |
573 #endif | 596 #endif |
574 } | 597 } |
575 | 598 |
576 | 599 |
| 600 Object* KeyedCallIC::LoadFunction(State state, |
| 601 Handle<Object> object, |
| 602 Handle<Object> key) { |
| 603 if (key->IsSymbol()) { |
| 604 return CallICBase::LoadFunction(state, object, Handle<String>::cast(key)); |
| 605 } |
| 606 |
| 607 if (object->IsUndefined() || object->IsNull()) { |
| 608 return TypeError("non_object_property_call", object, key); |
| 609 } |
| 610 |
| 611 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
| 612 ReceiverToObject(object); |
| 613 } else { |
| 614 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { |
| 615 int argc = target()->arguments_count(); |
| 616 InLoopFlag in_loop = target()->ic_in_loop(); |
| 617 Object* code = StubCache::ComputeCallMegamorphic( |
| 618 argc, in_loop, Code::KEYED_CALL_IC); |
| 619 if (!code->IsFailure()) { |
| 620 set_target(Code::cast(code)); |
| 621 } |
| 622 } |
| 623 } |
| 624 Object* result = Runtime::GetObjectProperty(object, key); |
| 625 if (result->IsJSFunction()) return result; |
| 626 result = TryCallAsFunction(result); |
| 627 return result->IsJSFunction() ? |
| 628 result : TypeError("property_not_function", object, key); |
| 629 } |
| 630 |
| 631 |
577 Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { | 632 Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { |
578 // If the object is undefined or null it's illegal to try to get any | 633 // If the object is undefined or null it's illegal to try to get any |
579 // of its properties; throw a TypeError in that case. | 634 // of its properties; throw a TypeError in that case. |
580 if (object->IsUndefined() || object->IsNull()) { | 635 if (object->IsUndefined() || object->IsNull()) { |
581 return TypeError("non_object_property_load", object, name); | 636 return TypeError("non_object_property_load", object, name); |
582 } | 637 } |
583 | 638 |
584 if (FLAG_use_ic) { | 639 if (FLAG_use_ic) { |
585 // Use specialized code for getting the length of strings and | 640 // Use specialized code for getting the length of strings and |
586 // string wrapper objects. The length property of string wrapper | 641 // string wrapper objects. The length property of string wrapper |
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1286 #ifdef DEBUG | 1341 #ifdef DEBUG |
1287 TraceIC("KeyedStoreIC", name, state, target()); | 1342 TraceIC("KeyedStoreIC", name, state, target()); |
1288 #endif | 1343 #endif |
1289 } | 1344 } |
1290 | 1345 |
1291 | 1346 |
1292 // ---------------------------------------------------------------------------- | 1347 // ---------------------------------------------------------------------------- |
1293 // Static IC stub generators. | 1348 // Static IC stub generators. |
1294 // | 1349 // |
1295 | 1350 |
1296 // Used from ic_<arch>.cc. | 1351 static Object* CompileFunction(Object* result, |
| 1352 Handle<Object> object, |
| 1353 InLoopFlag in_loop) { |
| 1354 // Compile now with optimization. |
| 1355 HandleScope scope; |
| 1356 Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result)); |
| 1357 if (in_loop == IN_LOOP) { |
| 1358 CompileLazyInLoop(function, object, CLEAR_EXCEPTION); |
| 1359 } else { |
| 1360 CompileLazy(function, object, CLEAR_EXCEPTION); |
| 1361 } |
| 1362 return *function; |
| 1363 } |
| 1364 |
| 1365 |
| 1366 // Used from ic-<arch>.cc. |
1297 Object* CallIC_Miss(Arguments args) { | 1367 Object* CallIC_Miss(Arguments args) { |
1298 NoHandleAllocation na; | 1368 NoHandleAllocation na; |
1299 ASSERT(args.length() == 2); | 1369 ASSERT(args.length() == 2); |
1300 CallIC ic; | 1370 CallIC ic; |
1301 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1371 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1302 Object* result = | 1372 Object* result = |
1303 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); | 1373 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); |
1304 | 1374 |
1305 // The first time the inline cache is updated may be the first time the | 1375 // The first time the inline cache is updated may be the first time the |
1306 // function it references gets called. If the function was lazily compiled | 1376 // function it references gets called. If the function was lazily compiled |
1307 // then the first call will trigger a compilation. We check for this case | 1377 // then the first call will trigger a compilation. We check for this case |
1308 // and we do the compilation immediately, instead of waiting for the stub | 1378 // and we do the compilation immediately, instead of waiting for the stub |
1309 // currently attached to the JSFunction object to trigger compilation. We | 1379 // currently attached to the JSFunction object to trigger compilation. We |
1310 // do this in the case where we know that the inline cache is inside a loop, | 1380 // do this in the case where we know that the inline cache is inside a loop, |
1311 // because then we know that we want to optimize the function. | 1381 // because then we know that we want to optimize the function. |
1312 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1382 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { |
1313 return result; | 1383 return result; |
1314 } | 1384 } |
1315 | 1385 return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop()); |
1316 // Compile now with optimization. | |
1317 HandleScope scope; | |
1318 Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result)); | |
1319 InLoopFlag in_loop = ic.target()->ic_in_loop(); | |
1320 if (in_loop == IN_LOOP) { | |
1321 CompileLazyInLoop(function, args.at<Object>(0), CLEAR_EXCEPTION); | |
1322 } else { | |
1323 CompileLazy(function, args.at<Object>(0), CLEAR_EXCEPTION); | |
1324 } | |
1325 return *function; | |
1326 } | 1386 } |
1327 | 1387 |
1328 | 1388 |
1329 // Used from ic_<arch>.cc. | 1389 // Used from ic-<arch>.cc. |
| 1390 Object* KeyedCallIC_Miss(Arguments args) { |
| 1391 NoHandleAllocation na; |
| 1392 ASSERT(args.length() == 2); |
| 1393 KeyedCallIC ic; |
| 1394 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| 1395 Object* result = |
| 1396 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); |
| 1397 |
| 1398 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { |
| 1399 return result; |
| 1400 } |
| 1401 return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop()); |
| 1402 } |
| 1403 |
| 1404 |
| 1405 // Used from ic-<arch>.cc. |
1330 Object* LoadIC_Miss(Arguments args) { | 1406 Object* LoadIC_Miss(Arguments args) { |
1331 NoHandleAllocation na; | 1407 NoHandleAllocation na; |
1332 ASSERT(args.length() == 2); | 1408 ASSERT(args.length() == 2); |
1333 LoadIC ic; | 1409 LoadIC ic; |
1334 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1410 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1335 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 1411 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
1336 } | 1412 } |
1337 | 1413 |
1338 | 1414 |
1339 // Used from ic_<arch>.cc | 1415 // Used from ic-<arch>.cc |
1340 Object* KeyedLoadIC_Miss(Arguments args) { | 1416 Object* KeyedLoadIC_Miss(Arguments args) { |
1341 NoHandleAllocation na; | 1417 NoHandleAllocation na; |
1342 ASSERT(args.length() == 2); | 1418 ASSERT(args.length() == 2); |
1343 KeyedLoadIC ic; | 1419 KeyedLoadIC ic; |
1344 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1420 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1345 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); | 1421 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); |
1346 } | 1422 } |
1347 | 1423 |
1348 | 1424 |
1349 // Used from ic_<arch>.cc. | 1425 // Used from ic-<arch>.cc. |
1350 Object* StoreIC_Miss(Arguments args) { | 1426 Object* StoreIC_Miss(Arguments args) { |
1351 NoHandleAllocation na; | 1427 NoHandleAllocation na; |
1352 ASSERT(args.length() == 3); | 1428 ASSERT(args.length() == 3); |
1353 StoreIC ic; | 1429 StoreIC ic; |
1354 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1430 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1355 return ic.Store(state, args.at<Object>(0), args.at<String>(1), | 1431 return ic.Store(state, args.at<Object>(0), args.at<String>(1), |
1356 args.at<Object>(2)); | 1432 args.at<Object>(2)); |
1357 } | 1433 } |
1358 | 1434 |
1359 | 1435 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 | 1473 |
1398 // Set the new property value and do the map transition. | 1474 // Set the new property value and do the map transition. |
1399 object->set_properties(new_storage); | 1475 object->set_properties(new_storage); |
1400 object->set_map(transition); | 1476 object->set_map(transition); |
1401 | 1477 |
1402 // Return the stored value. | 1478 // Return the stored value. |
1403 return value; | 1479 return value; |
1404 } | 1480 } |
1405 | 1481 |
1406 | 1482 |
1407 // Used from ic_<arch>.cc. | 1483 // Used from ic-<arch>.cc. |
1408 Object* KeyedStoreIC_Miss(Arguments args) { | 1484 Object* KeyedStoreIC_Miss(Arguments args) { |
1409 NoHandleAllocation na; | 1485 NoHandleAllocation na; |
1410 ASSERT(args.length() == 3); | 1486 ASSERT(args.length() == 3); |
1411 KeyedStoreIC ic; | 1487 KeyedStoreIC ic; |
1412 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1488 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1413 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), | 1489 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), |
1414 args.at<Object>(2)); | 1490 args.at<Object>(2)); |
1415 } | 1491 } |
1416 | 1492 |
1417 | 1493 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 #undef ADDR | 1586 #undef ADDR |
1511 }; | 1587 }; |
1512 | 1588 |
1513 | 1589 |
1514 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1590 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
1515 return IC_utilities[id]; | 1591 return IC_utilities[id]; |
1516 } | 1592 } |
1517 | 1593 |
1518 | 1594 |
1519 } } // namespace v8::internal | 1595 } } // namespace v8::internal |
OLD | NEW |