Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Side by Side Diff: src/ic.cc

Issue 2959: Revert revision 331. The propagation of monomorphic prototype failure... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 } 54 }
55 UNREACHABLE(); 55 UNREACHABLE();
56 return 0; 56 return 0;
57 } 57 }
58 58
59 void IC::TraceIC(const char* type, 59 void IC::TraceIC(const char* type,
60 Handle<String> name, 60 Handle<String> name,
61 State old_state, 61 State old_state,
62 Code* new_target) { 62 Code* new_target) {
63 if (FLAG_trace_ic) { 63 if (FLAG_trace_ic) {
64 State new_state = new_target->ic_state(); 64 State new_state = StateFrom(new_target, Heap::undefined_value());
65 PrintF("[%s (%c->%c) ", type, 65 PrintF("[%s (%c->%c) ", type,
66 TransitionMarkFromState(old_state), 66 TransitionMarkFromState(old_state),
67 TransitionMarkFromState(new_state)); 67 TransitionMarkFromState(new_state));
68 name->Print(); 68 name->Print();
69 PrintF("]\n"); 69 PrintF("]\n");
70 } 70 }
71 } 71 }
72 #endif 72 #endif
73 73
74 74
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 // normally would be. 120 // normally would be.
121 Address addr = pc() - Assembler::kTargetAddrToReturnAddrDist; 121 Address addr = pc() - Assembler::kTargetAddrToReturnAddrDist;
122 // Return the address in the original code. This is the place where 122 // Return the address in the original code. This is the place where
123 // the call which has been overwriten by the DebugBreakXXX resides 123 // the call which has been overwriten by the DebugBreakXXX resides
124 // and the place where the inline cache system should look. 124 // and the place where the inline cache system should look.
125 int delta = original_code->instruction_start() - code->instruction_start(); 125 int delta = original_code->instruction_start() - code->instruction_start();
126 return addr + delta; 126 return addr + delta;
127 } 127 }
128 128
129 129
130 IC::State IC::ComputeCacheState(Code* target, Object* receiver, 130 IC::State IC::StateFrom(Code* target, Object* receiver) {
131 Object* name, Object** new_target) { 131 IC::State state = target->ic_state();
132 // Get the raw state from the target.
133 State target_state = target->ic_state();
134 132
135 // Assume that no new target exists in the cache. 133 if (state != MONOMORPHIC) return state;
136 *new_target = Heap::undefined_value(); 134 if (receiver->IsUndefined() || receiver->IsNull()) return state;
137
138 if (target_state != MONOMORPHIC) return target_state;
139 if (receiver->IsUndefined() || receiver->IsNull()) return target_state;
140 135
141 Map* map = GetCodeCacheMapForObject(receiver); 136 Map* map = GetCodeCacheMapForObject(receiver);
142 137
143 // Decide whether the inline cache failed because of changes to the 138 // Decide whether the inline cache failed because of changes to the
144 // receiver itself or changes to one of its prototypes. 139 // receiver itself or changes to one of its prototypes.
145 // 140 //
146 // If there are changes to the receiver itself, the map of the 141 // If there are changes to the receiver itself, the map of the
147 // receiver will have changed and the current target will not be in 142 // receiver will have changed and the current target will not be in
148 // the receiver map's code cache. Therefore, if the current target 143 // the receiver map's code cache. Therefore, if the current target
149 // is in the receiver map's code cache, the inline cache failed due 144 // is in the receiver map's code cache, the inline cache failed due
150 // to prototype check failure. 145 // to prototype check failure.
151 int index = -1; 146 int index = map->IndexInCodeCache(target);
152 Object* code = NULL; 147 if (index >= 0) {
153 if (name->IsString()) {
154 code = map->FindIndexInCodeCache(String::cast(name),
155 target->flags(),
156 &index);
157 }
158 if (index >= 0 && code == target) {
159 // For keyed load/store, the most likely cause of cache failure is 148 // For keyed load/store, the most likely cause of cache failure is
160 // that the key has changed. We do not distinguish between 149 // that the key has changed. We do not distinguish between
161 // prototype and non-prototype failures for keyed access. 150 // prototype and non-prototype failures for keyed access.
162 Code::Kind kind = target->kind(); 151 Code::Kind kind = target->kind();
163 if (kind == Code::KEYED_LOAD_IC || kind == Code::KEYED_STORE_IC) { 152 if (kind == Code::KEYED_LOAD_IC || kind == Code::KEYED_STORE_IC) {
164 return MONOMORPHIC; 153 return MONOMORPHIC;
165 } 154 }
166 155
167 // Remove the target from the code cache to avoid hitting the same 156 // Remove the target from the code cache to avoid hitting the same
168 // invalid stub again. 157 // invalid stub again.
169 map->RemoveFromCodeCache(index); 158 map->RemoveFromCodeCache(index);
170 159
171 return MONOMORPHIC_PROTOTYPE_FAILURE; 160 return MONOMORPHIC_PROTOTYPE_FAILURE;
172 } 161 }
173 162
174 // The builtins object is special. It only changes when JavaScript 163 // The builtins object is special. It only changes when JavaScript
175 // builtins are loaded lazily. It is important to keep inline 164 // builtins are loaded lazily. It is important to keep inline
176 // caches for the builtins object monomorphic. Therefore, if we get 165 // caches for the builtins object monomorphic. Therefore, if we get
177 // an inline cache miss for the builtins object after lazily loading 166 // an inline cache miss for the builtins object after lazily loading
178 // JavaScript builtins, we clear the code cache and return 167 // JavaScript builtins, we clear the code cache and return
179 // uninitialized as the state to force the inline cache back to 168 // uninitialized as the state to force the inline cache back to
180 // monomorphic state. 169 // monomorphic state.
181 if (receiver->IsJSBuiltinsObject()) { 170 if (receiver->IsJSBuiltinsObject()) {
182 map->ClearCodeCache(); 171 map->ClearCodeCache();
183 return UNINITIALIZED; 172 return UNINITIALIZED;
184 } 173 }
185 174
186 *new_target = code;
187 return MONOMORPHIC; 175 return MONOMORPHIC;
188 } 176 }
189 177
190 178
191 RelocMode IC::ComputeMode() { 179 RelocMode IC::ComputeMode() {
192 Address addr = address(); 180 Address addr = address();
193 Code* code = Code::cast(Heap::FindCodeObject(addr)); 181 Code* code = Code::cast(Heap::FindCodeObject(addr));
194 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); 182 for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
195 !it.done(); it.next()) { 183 !it.done(); it.next()) {
196 RelocInfo* info = it.rinfo(); 184 RelocInfo* info = it.rinfo();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 StackFrameLocator locator; 268 StackFrameLocator locator;
281 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 269 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
282 int index = frame->ComputeExpressionsCount() - (argc + 1); 270 int index = frame->ComputeExpressionsCount() - (argc + 1);
283 frame->SetExpression(index, *target); 271 frame->SetExpression(index, *target);
284 } 272 }
285 273
286 return *delegate; 274 return *delegate;
287 } 275 }
288 276
289 277
290 Object* CallIC::LoadFunction(Handle<Object> object, 278 Object* CallIC::LoadFunction(State state,
279 Handle<Object> object,
291 Handle<String> name) { 280 Handle<String> name) {
292 // If the object is undefined or null it's illegal to try to get any 281 // If the object is undefined or null it's illegal to try to get any
293 // of its properties; throw a TypeError in that case. 282 // of its properties; throw a TypeError in that case.
294 if (object->IsUndefined() || object->IsNull()) { 283 if (object->IsUndefined() || object->IsNull()) {
295 return TypeError("non_object_property_call", object, name); 284 return TypeError("non_object_property_call", object, name);
296 } 285 }
297 286
298 Object* result = Heap::the_hole_value(); 287 Object* result = Heap::the_hole_value();
299 288
300 // Check if the name is trivially convertible to an index and get 289 // Check if the name is trivially convertible to an index and get
(...skipping 18 matching lines...) Expand all
319 // If the object does not have the requested property, check which 308 // If the object does not have the requested property, check which
320 // exception we need to throw. 309 // exception we need to throw.
321 if (is_contextual()) { 310 if (is_contextual()) {
322 return ReferenceError("not_defined", name); 311 return ReferenceError("not_defined", name);
323 } 312 }
324 return TypeError("undefined_method", object, name); 313 return TypeError("undefined_method", object, name);
325 } 314 }
326 315
327 // Lookup is valid: Update inline cache and stub cache. 316 // Lookup is valid: Update inline cache and stub cache.
328 if (FLAG_use_ic && lookup.IsLoaded()) { 317 if (FLAG_use_ic && lookup.IsLoaded()) {
329 UpdateCaches(&lookup, object, name); 318 UpdateCaches(&lookup, state, object, name);
330 } 319 }
331 320
332 if (lookup.type() == INTERCEPTOR) { 321 if (lookup.type() == INTERCEPTOR) {
333 // Get the property. 322 // Get the property.
334 PropertyAttributes attr; 323 PropertyAttributes attr;
335 result = object->GetProperty(*name, &attr); 324 result = object->GetProperty(*name, &attr);
336 if (result->IsFailure()) return result; 325 if (result->IsFailure()) return result;
337 // If the object does not have the requested property, check which 326 // If the object does not have the requested property, check which
338 // exception we need to throw. 327 // exception we need to throw.
339 if (attr == ABSENT) { 328 if (attr == ABSENT) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 } 367 }
379 368
380 // Try to find a suitable function delegate for the object at hand. 369 // Try to find a suitable function delegate for the object at hand.
381 result = TryCallAsFunction(result); 370 result = TryCallAsFunction(result);
382 return result->IsJSFunction() ? 371 return result->IsJSFunction() ?
383 result : TypeError("property_not_function", object, name); 372 result : TypeError("property_not_function", object, name);
384 } 373 }
385 374
386 375
387 void CallIC::UpdateCaches(LookupResult* lookup, 376 void CallIC::UpdateCaches(LookupResult* lookup,
377 State state,
388 Handle<Object> object, 378 Handle<Object> object,
389 Handle<String> name) { 379 Handle<String> name) {
390 ASSERT(lookup->IsLoaded()); 380 ASSERT(lookup->IsLoaded());
391 // Bail out if we didn't find a result. 381 // Bail out if we didn't find a result.
392 if (!lookup->IsValid() || !lookup->IsCacheable()) return; 382 if (!lookup->IsValid() || !lookup->IsCacheable()) return;
393 383
394 // Compute the number of arguments. 384 // Compute the number of arguments.
395 int argc = target()->arguments_count(); 385 int argc = target()->arguments_count();
386 Object* code = NULL;
396 387
397 Object* code = Heap::undefined_value(); 388 if (state == UNINITIALIZED) {
398 State state = ComputeCacheState(target(), *object, *name, &code); 389 // This is the first time we execute this inline cache.
399 390 // Set the target to the pre monomorphic stub to delay
400 switch (state) { 391 // setting the monomorphic state.
401 case UNINITIALIZED: 392 code = StubCache::ComputeCallPreMonomorphic(argc);
402 code = StubCache::ComputeCallPreMonomorphic(argc); 393 } else if (state == MONOMORPHIC) {
403 break; 394 code = StubCache::ComputeCallMegamorphic(argc);
404 case MONOMORPHIC: 395 } else {
405 if (code->IsUndefined()) code = StubCache::ComputeCallMegamorphic(argc); 396 // Compute monomorphic stub.
406 break; 397 switch (lookup->type()) {
407 default: 398 case FIELD: {
408 // Compute monomorphic stub. 399 int index = lookup->GetFieldIndex();
409 switch (lookup->type()) { 400 code = StubCache::ComputeCallField(argc, *name, *object,
410 case FIELD: { 401 lookup->holder(), index);
411 int index = lookup->GetFieldIndex(); 402 break;
412 code = StubCache::ComputeCallField(argc, *name, *object,
413 lookup->holder(), index);
414 break;
415 }
416 case CONSTANT_FUNCTION: {
417 // Get the constant function and compute the code stub for this
418 // call; used for rewriting to monomorphic state and making sure
419 // that the code stub is in the stub cache.
420 JSFunction* function = lookup->GetConstantFunction();
421 code = StubCache::ComputeCallConstant(argc, *name, *object,
422 lookup->holder(), function);
423 break;
424 }
425 case NORMAL: {
426 // There is only one shared stub for calling normalized
427 // properties. It does not traverse the prototype chain, so the
428 // property must be found in the receiver for the stub to be
429 // applicable.
430 if (!object->IsJSObject()) return;
431 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
432 if (lookup->holder() != *receiver) return;
433 code = StubCache::ComputeCallNormal(argc, *name, *receiver);
434 break;
435 }
436 case INTERCEPTOR: {
437 code = StubCache::ComputeCallInterceptor(argc, *name, *object,
438 lookup->holder());
439 break;
440 }
441 default:
442 return;
443 } 403 }
444 break; 404 case CONSTANT_FUNCTION: {
405 // Get the constant function and compute the code stub for this
406 // call; used for rewriting to monomorphic state and making sure
407 // that the code stub is in the stub cache.
408 JSFunction* function = lookup->GetConstantFunction();
409 code = StubCache::ComputeCallConstant(argc, *name, *object,
410 lookup->holder(), function);
411 break;
412 }
413 case NORMAL: {
414 // There is only one shared stub for calling normalized
415 // properties. It does not traverse the prototype chain, so the
416 // property must be found in the receiver for the stub to be
417 // applicable.
418 if (!object->IsJSObject()) return;
419 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
420 if (lookup->holder() != *receiver) return;
421 code = StubCache::ComputeCallNormal(argc, *name, *receiver);
422 break;
423 }
424 case INTERCEPTOR: {
425 code = StubCache::ComputeCallInterceptor(argc, *name, *object,
426 lookup->holder());
427 break;
428 }
429 default:
430 return;
431 }
445 } 432 }
446 433
447 // If we're unable to compute the stub (not enough memory left), we 434 // If we're unable to compute the stub (not enough memory left), we
448 // simply avoid updating the caches. 435 // simply avoid updating the caches.
449 if (code->IsFailure()) return; 436 if (code->IsFailure()) return;
450 437
451 // Patch the call site depending on the state of the cache. 438 // Patch the call site depending on the state of the cache.
452 if (state == UNINITIALIZED || state == PREMONOMORPHIC || 439 if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
453 state == MONOMORPHIC || state == MONOMORPHIC_PROTOTYPE_FAILURE) { 440 state == MONOMORPHIC || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
454 set_target(Code::cast(code)); 441 set_target(Code::cast(code));
455 } 442 }
456 443
457 #ifdef DEBUG 444 #ifdef DEBUG
458 TraceIC("CallIC", name, state, target()); 445 TraceIC("CallIC", name, state, target());
459 #endif 446 #endif
460 } 447 }
461 448
462 449
463 Object* LoadIC::Load(Handle<Object> object, Handle<String> name) { 450 Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
464 // If the object is undefined or null it's illegal to try to get any 451 // If the object is undefined or null it's illegal to try to get any
465 // of its properties; throw a TypeError in that case. 452 // of its properties; throw a TypeError in that case.
466 if (object->IsUndefined() || object->IsNull()) { 453 if (object->IsUndefined() || object->IsNull()) {
467 return TypeError("non_object_property_load", object, name); 454 return TypeError("non_object_property_load", object, name);
468 } 455 }
469 456
470 if (FLAG_use_ic) { 457 if (FLAG_use_ic) {
471 // Use specialized code for getting the length of strings. 458 // Use specialized code for getting the length of strings.
472 if (object->IsString() && name->Equals(Heap::length_symbol())) { 459 if (object->IsString() && name->Equals(Heap::length_symbol())) {
473 #ifdef DEBUG 460 #ifdef DEBUG
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 } 513 }
527 String* class_name = object->IsJSObject() 514 String* class_name = object->IsJSObject()
528 ? Handle<JSObject>::cast(object)->class_name() 515 ? Handle<JSObject>::cast(object)->class_name()
529 : Heap::empty_string(); 516 : Heap::empty_string();
530 LOG(SuspectReadEvent(*name, class_name)); 517 LOG(SuspectReadEvent(*name, class_name));
531 USE(class_name); 518 USE(class_name);
532 } 519 }
533 520
534 // Update inline cache and stub cache. 521 // Update inline cache and stub cache.
535 if (FLAG_use_ic && lookup.IsLoaded()) { 522 if (FLAG_use_ic && lookup.IsLoaded()) {
536 UpdateCaches(&lookup, object, name); 523 UpdateCaches(&lookup, state, object, name);
537 } 524 }
538 525
539 PropertyAttributes attr; 526 PropertyAttributes attr;
540 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { 527 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) {
541 // Get the property. 528 // Get the property.
542 Object* result = object->GetProperty(*object, &lookup, *name, &attr); 529 Object* result = object->GetProperty(*object, &lookup, *name, &attr);
543 if (result->IsFailure()) return result; 530 if (result->IsFailure()) return result;
544 // If the property is not present, check if we need to throw an 531 // If the property is not present, check if we need to throw an
545 // exception. 532 // exception.
546 if (attr == ABSENT && is_contextual()) { 533 if (attr == ABSENT && is_contextual()) {
547 return ReferenceError("not_defined", name); 534 return ReferenceError("not_defined", name);
548 } 535 }
549 return result; 536 return result;
550 } 537 }
551 538
552 // Get the property. 539 // Get the property.
553 return object->GetProperty(*object, &lookup, *name, &attr); 540 return object->GetProperty(*object, &lookup, *name, &attr);
554 } 541 }
555 542
556 543
557 void LoadIC::UpdateCaches(LookupResult* lookup, 544 void LoadIC::UpdateCaches(LookupResult* lookup,
545 State state,
558 Handle<Object> object, 546 Handle<Object> object,
559 Handle<String> name) { 547 Handle<String> name) {
560 ASSERT(lookup->IsLoaded()); 548 ASSERT(lookup->IsLoaded());
561 // Bail out if we didn't find a result. 549 // Bail out if we didn't find a result.
562 if (!lookup->IsValid() || !lookup->IsCacheable()) return; 550 if (!lookup->IsValid() || !lookup->IsCacheable()) return;
563 551
564 // Loading properties from values is not common, so don't try to 552 // Loading properties from values is not common, so don't try to
565 // deal with non-JS objects here. 553 // deal with non-JS objects here.
566 if (!object->IsJSObject()) return; 554 if (!object->IsJSObject()) return;
567 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 555 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
568 556
569 // Compute the code stub for this load. 557 // Compute the code stub for this load.
570 Object* code = Heap::undefined_value(); 558 Object* code = NULL;
571 State state = ComputeCacheState(target(), *object, *name, &code);
572
573 if (state == UNINITIALIZED) { 559 if (state == UNINITIALIZED) {
574 // This is the first time we execute this inline cache. 560 // This is the first time we execute this inline cache.
575 // Set the target to the pre monomorphic stub to delay 561 // Set the target to the pre monomorphic stub to delay
576 // setting the monomorphic state. 562 // setting the monomorphic state.
577 code = pre_monomorphic_stub(); 563 code = pre_monomorphic_stub();
578 } else if (state != MONOMORPHIC) { 564 } else {
579 // Compute monomorphic stub. 565 // Compute monomorphic stub.
580 switch (lookup->type()) { 566 switch (lookup->type()) {
581 case FIELD: { 567 case FIELD: {
582 code = StubCache::ComputeLoadField(*name, *receiver, 568 code = StubCache::ComputeLoadField(*name, *receiver,
583 lookup->holder(), 569 lookup->holder(),
584 lookup->GetFieldIndex()); 570 lookup->GetFieldIndex());
585 break; 571 break;
586 } 572 }
587 case CONSTANT_FUNCTION: { 573 case CONSTANT_FUNCTION: {
588 Object* constant = lookup->GetConstantFunction(); 574 Object* constant = lookup->GetConstantFunction();
(...skipping 20 matching lines...) Expand all
609 break; 595 break;
610 } 596 }
611 case INTERCEPTOR: { 597 case INTERCEPTOR: {
612 code = StubCache::ComputeLoadInterceptor(*name, *receiver, 598 code = StubCache::ComputeLoadInterceptor(*name, *receiver,
613 lookup->holder()); 599 lookup->holder());
614 break; 600 break;
615 } 601 }
616 default: 602 default:
617 return; 603 return;
618 } 604 }
605 }
619 606
620 // If we're unable to compute the stub (not enough memory left), we 607 // If we're unable to compute the stub (not enough memory left), we
621 // simply avoid updating the caches. 608 // simply avoid updating the caches.
622 if (code->IsFailure()) return; 609 if (code->IsFailure()) return;
623 }
624 610
625 // Patch the call site depending on the state of the cache. 611 // Patch the call site depending on the state of the cache.
626 if (state == UNINITIALIZED || state == PREMONOMORPHIC || 612 if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
627 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 613 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
628 set_target(Code::cast(code)); 614 set_target(Code::cast(code));
629 } else if (state == MONOMORPHIC && code->IsUndefined()) { 615 } else if (state == MONOMORPHIC) {
630 set_target(megamorphic_stub()); 616 set_target(megamorphic_stub());
631 } else if (state == MONOMORPHIC) {
632 set_target(Code::cast(code));
633 } 617 }
634 618
635 #ifdef DEBUG 619 #ifdef DEBUG
636 TraceIC("LoadIC", name, state, target()); 620 TraceIC("LoadIC", name, state, target());
637 #endif 621 #endif
638 } 622 }
639 623
640 624
641 Object* KeyedLoadIC::Load(Handle<Object> object, 625 Object* KeyedLoadIC::Load(State state,
626 Handle<Object> object,
642 Handle<Object> key) { 627 Handle<Object> key) {
643 if (key->IsSymbol()) { 628 if (key->IsSymbol()) {
644 Handle<String> name = Handle<String>::cast(key); 629 Handle<String> name = Handle<String>::cast(key);
645 630
646 // If the object is undefined or null it's illegal to try to get any 631 // If the object is undefined or null it's illegal to try to get any
647 // of its properties; throw a TypeError in that case. 632 // of its properties; throw a TypeError in that case.
648 if (object->IsUndefined() || object->IsNull()) { 633 if (object->IsUndefined() || object->IsNull()) {
649 return TypeError("non_object_property_load", object, name); 634 return TypeError("non_object_property_load", object, name);
650 } 635 }
651 636
652 if (FLAG_use_ic) { 637 if (FLAG_use_ic) {
653 // Use specialized code for getting the length of strings. 638 // Use specialized code for getting the length of strings.
654 if (object->IsString() && name->Equals(Heap::length_symbol())) { 639 if (object->IsString() && name->Equals(Heap::length_symbol())) {
655 Handle<String> string = Handle<String>::cast(object); 640 Handle<String> string = Handle<String>::cast(object);
656 Object* code = NULL; 641 Object* code = NULL;
657 if (string->IsShortString()) { 642 if (string->IsShortString()) {
658 code = StubCache::ComputeKeyedLoadShortStringLength(*name, *string); 643 code = StubCache::ComputeKeyedLoadShortStringLength(*name, *string);
659 } else if (string->IsMediumString()) { 644 } else if (string->IsMediumString()) {
660 code = 645 code =
661 StubCache::ComputeKeyedLoadMediumStringLength(*name, *string); 646 StubCache::ComputeKeyedLoadMediumStringLength(*name, *string);
662 } else { 647 } else {
663 ASSERT(string->IsLongString()); 648 ASSERT(string->IsLongString());
664 code = StubCache::ComputeKeyedLoadLongStringLength(*name, *string); 649 code = StubCache::ComputeKeyedLoadLongStringLength(*name, *string);
665 } 650 }
666 if (code->IsFailure()) return code; 651 if (code->IsFailure()) return code;
667 set_target(Code::cast(code)); 652 set_target(Code::cast(code));
668 #ifdef DEBUG 653 #ifdef DEBUG
669 if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#length /string]\n"); 654 TraceIC("KeyedLoadIC", name, state, target());
670 #endif 655 #endif
671 return Smi::FromInt(string->length()); 656 return Smi::FromInt(string->length());
672 } 657 }
673 658
674 // Use specialized code for getting the length of arrays. 659 // Use specialized code for getting the length of arrays.
675 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { 660 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
676 Handle<JSArray> array = Handle<JSArray>::cast(object); 661 Handle<JSArray> array = Handle<JSArray>::cast(object);
677 Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array); 662 Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array);
678 if (code->IsFailure()) return code; 663 if (code->IsFailure()) return code;
679 set_target(Code::cast(code)); 664 set_target(Code::cast(code));
680 #ifdef DEBUG 665 #ifdef DEBUG
681 if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#length /array]\n"); 666 TraceIC("KeyedLoadIC", name, state, target());
682 #endif 667 #endif
683 return JSArray::cast(*object)->length(); 668 return JSArray::cast(*object)->length();
684 } 669 }
685 670
686 // Use specialized code for getting prototype of functions. 671 // Use specialized code for getting prototype of functions.
687 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) { 672 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) {
688 Handle<JSFunction> function = Handle<JSFunction>::cast(object); 673 Handle<JSFunction> function = Handle<JSFunction>::cast(object);
689 Object* code = 674 Object* code =
690 StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); 675 StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);
691 if (code->IsFailure()) return code; 676 if (code->IsFailure()) return code;
692 set_target(Code::cast(code)); 677 set_target(Code::cast(code));
693 #ifdef DEBUG 678 #ifdef DEBUG
694 if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#prototype /function]\n"); 679 TraceIC("KeyedLoadIC", name, state, target());
695 #endif 680 #endif
696 return Accessors::FunctionGetPrototype(*object, 0); 681 return Accessors::FunctionGetPrototype(*object, 0);
697 } 682 }
698 } 683 }
699 684
700 // Check if the name is trivially convertible to an index and get 685 // Check if the name is trivially convertible to an index and get
701 // the element or char if so. 686 // the element or char if so.
702 uint32_t index = 0; 687 uint32_t index = 0;
703 if (name->AsArrayIndex(&index)) { 688 if (name->AsArrayIndex(&index)) {
704 HandleScope scope; 689 HandleScope scope;
705 // Rewrite to the generic keyed load stub. 690 // Rewrite to the generic keyed load stub.
706 if (FLAG_use_ic) set_target(generic_stub()); 691 if (FLAG_use_ic) set_target(generic_stub());
707 return Runtime::GetElementOrCharAt(object, index); 692 return Runtime::GetElementOrCharAt(object, index);
708 } 693 }
709 694
710 // Named lookup. 695 // Named lookup.
711 LookupResult lookup; 696 LookupResult lookup;
712 object->Lookup(*name, &lookup); 697 object->Lookup(*name, &lookup);
713 698
714 // If lookup is invalid, check if we need to throw an exception. 699 // If lookup is invalid, check if we need to throw an exception.
715 if (!lookup.IsValid()) { 700 if (!lookup.IsValid()) {
716 if (FLAG_strict || is_contextual()) { 701 if (FLAG_strict || is_contextual()) {
717 return ReferenceError("not_defined", name); 702 return ReferenceError("not_defined", name);
718 } 703 }
719 } 704 }
720 705
721 // Update the inline cache. 706 // Update the inline cache.
722 if (FLAG_use_ic && lookup.IsLoaded()) { 707 if (FLAG_use_ic && lookup.IsLoaded()) {
723 UpdateCaches(&lookup, object, name); 708 UpdateCaches(&lookup, state, object, name);
724 } 709 }
725 710
726 PropertyAttributes attr; 711 PropertyAttributes attr;
727 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { 712 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) {
728 // Get the property. 713 // Get the property.
729 Object* result = object->GetProperty(*object, &lookup, *name, &attr); 714 Object* result = object->GetProperty(*object, &lookup, *name, &attr);
730 if (result->IsFailure()) return result; 715 if (result->IsFailure()) return result;
731 // If the property is not present, check if we need to throw an 716 // If the property is not present, check if we need to throw an
732 // exception. 717 // exception.
733 if (attr == ABSENT && is_contextual()) { 718 if (attr == ABSENT && is_contextual()) {
734 return ReferenceError("not_defined", name); 719 return ReferenceError("not_defined", name);
735 } 720 }
736 return result; 721 return result;
737 } 722 }
738 723
739 return object->GetProperty(*object, &lookup, *name, &attr); 724 return object->GetProperty(*object, &lookup, *name, &attr);
740 } 725 }
741 726
742 // Do not use ICs for objects that require access checks (including 727 // Do not use ICs for objects that require access checks (including
743 // the global object). 728 // the global object).
744 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 729 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
745 730
746 if (use_ic) set_target(generic_stub()); 731 if (use_ic) set_target(generic_stub());
747 732
748 // Get the property. 733 // Get the property.
749 return Runtime::GetObjectProperty(object, key); 734 return Runtime::GetObjectProperty(object, key);
750 } 735 }
751 736
752 737
753 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, 738 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
754 Handle<Object> object, 739 Handle<Object> object, Handle<String> name) {
755 Handle<String> name) {
756 ASSERT(lookup->IsLoaded()); 740 ASSERT(lookup->IsLoaded());
757 // Bail out if we didn't find a result. 741 // Bail out if we didn't find a result.
758 if (!lookup->IsValid() || !lookup->IsCacheable()) return; 742 if (!lookup->IsValid() || !lookup->IsCacheable()) return;
759 743
760 if (!object->IsJSObject()) return; 744 if (!object->IsJSObject()) return;
761 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 745 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
762 746
763 // Compute the state of the current inline cache. 747 // Compute the code stub for this load.
764 Object* code = Heap::undefined_value(); 748 Object* code = NULL;
765 State state = ComputeCacheState(target(), *object, *name, &code);
766 749
767 // Compute the code stub for this load.
768 if (state == UNINITIALIZED) { 750 if (state == UNINITIALIZED) {
769 // This is the first time we execute this inline cache. 751 // This is the first time we execute this inline cache.
770 // Set the target to the pre monomorphic stub to delay 752 // Set the target to the pre monomorphic stub to delay
771 // setting the monomorphic state. 753 // setting the monomorphic state.
772 code = pre_monomorphic_stub(); 754 code = pre_monomorphic_stub();
773 } else { 755 } else {
774 // Compute a monomorphic stub. 756 // Compute a monomorphic stub.
775 switch (lookup->type()) { 757 switch (lookup->type()) {
776 case FIELD: { 758 case FIELD: {
777 code = StubCache::ComputeKeyedLoadField(*name, *receiver, 759 code = StubCache::ComputeKeyedLoadField(*name, *receiver,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 } else if (state == MONOMORPHIC) { 802 } else if (state == MONOMORPHIC) {
821 set_target(megamorphic_stub()); 803 set_target(megamorphic_stub());
822 } 804 }
823 805
824 #ifdef DEBUG 806 #ifdef DEBUG
825 TraceIC("KeyedLoadIC", name, state, target()); 807 TraceIC("KeyedLoadIC", name, state, target());
826 #endif 808 #endif
827 } 809 }
828 810
829 811
830 Object* StoreIC::Store(Handle<Object> object, 812 Object* StoreIC::Store(State state,
813 Handle<Object> object,
831 Handle<String> name, 814 Handle<String> name,
832 Handle<Object> value) { 815 Handle<Object> value) {
833 // If the object is undefined or null it's illegal to try to set any 816 // If the object is undefined or null it's illegal to try to set any
834 // properties on it; throw a TypeError in that case. 817 // properties on it; throw a TypeError in that case.
835 if (object->IsUndefined() || object->IsNull()) { 818 if (object->IsUndefined() || object->IsNull()) {
836 return TypeError("non_object_property_store", object, name); 819 return TypeError("non_object_property_store", object, name);
837 } 820 }
838 821
839 // Ignore stores where the receiver is not a JSObject. 822 // Ignore stores where the receiver is not a JSObject.
840 if (!object->IsJSObject()) return *value; 823 if (!object->IsJSObject()) return *value;
841 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 824 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
842 825
843 // Check if the given name is an array index. 826 // Check if the given name is an array index.
844 uint32_t index; 827 uint32_t index;
845 if (name->AsArrayIndex(&index)) { 828 if (name->AsArrayIndex(&index)) {
846 HandleScope scope; 829 HandleScope scope;
847 Handle<Object> result = SetElement(receiver, index, value); 830 Handle<Object> result = SetElement(receiver, index, value);
848 if (result.is_null()) return Failure::Exception(); 831 if (result.is_null()) return Failure::Exception();
849 return *value; 832 return *value;
850 } 833 }
851 834
852 // Lookup the property locally in the receiver. 835 // Lookup the property locally in the receiver.
853 LookupResult lookup; 836 LookupResult lookup;
854 receiver->LocalLookup(*name, &lookup); 837 receiver->LocalLookup(*name, &lookup);
855 838
856 // Update inline cache and stub cache. 839 // Update inline cache and stub cache.
857 if (FLAG_use_ic && lookup.IsLoaded()) { 840 if (FLAG_use_ic && lookup.IsLoaded()) {
858 UpdateCaches(&lookup, receiver, name, value); 841 UpdateCaches(&lookup, state, receiver, name, value);
859 } 842 }
860 843
861 // Set the property. 844 // Set the property.
862 return receiver->SetProperty(*name, *value, NONE); 845 return receiver->SetProperty(*name, *value, NONE);
863 } 846 }
864 847
865 848
866 void StoreIC::UpdateCaches(LookupResult* lookup, 849 void StoreIC::UpdateCaches(LookupResult* lookup,
850 State state,
867 Handle<JSObject> receiver, 851 Handle<JSObject> receiver,
868 Handle<String> name, 852 Handle<String> name,
869 Handle<Object> value) { 853 Handle<Object> value) {
870 ASSERT(lookup->IsLoaded()); 854 ASSERT(lookup->IsLoaded());
871 // Bail out if we didn't find a result. 855 // Bail out if we didn't find a result.
872 if (!lookup->IsValid() || !lookup->IsCacheable()) return; 856 if (!lookup->IsValid() || !lookup->IsCacheable()) return;
873 857
874 // If the property is read-only, we leave the IC in its current 858 // If the property is read-only, we leave the IC in its current
875 // state. 859 // state.
876 if (lookup->IsReadOnly()) return; 860 if (lookup->IsReadOnly()) return;
877 861
878 // If the property has a non-field type allowing map transitions 862 // If the property has a non-field type allowing map transitions
879 // where there is extra room in the object, we leave the IC in its 863 // where there is extra room in the object, we leave the IC in its
880 // current state. 864 // current state.
881 PropertyType type = lookup->type(); 865 PropertyType type = lookup->type();
882 866
883 // Compute the state of the current inline cache.
884 Object* code = Heap::undefined_value();
885 State state = ComputeCacheState(target(), *receiver, *name, &code);
886
887 // Compute the code stub for this store; used for rewriting to 867 // Compute the code stub for this store; used for rewriting to
888 // monomorphic state and making sure that the code stub is in the 868 // monomorphic state and making sure that the code stub is in the
889 // stub cache. 869 // stub cache.
870 Object* code = NULL;
890 switch (type) { 871 switch (type) {
891 case FIELD: { 872 case FIELD: {
892 code = StubCache::ComputeStoreField(*name, *receiver, 873 code = StubCache::ComputeStoreField(*name, *receiver,
893 lookup->GetFieldIndex()); 874 lookup->GetFieldIndex());
894 break; 875 break;
895 } 876 }
896 case MAP_TRANSITION: { 877 case MAP_TRANSITION: {
897 if (lookup->GetAttributes() != NONE) return; 878 if (lookup->GetAttributes() != NONE) return;
898 if (receiver->map()->unused_property_fields() == 0) return; 879 if (receiver->map()->unused_property_fields() == 0) return;
899 HandleScope scope; 880 HandleScope scope;
(...skipping 29 matching lines...) Expand all
929 } else if (state == MONOMORPHIC) { 910 } else if (state == MONOMORPHIC) {
930 set_target(megamorphic_stub()); 911 set_target(megamorphic_stub());
931 } 912 }
932 913
933 #ifdef DEBUG 914 #ifdef DEBUG
934 TraceIC("StoreIC", name, state, target()); 915 TraceIC("StoreIC", name, state, target());
935 #endif 916 #endif
936 } 917 }
937 918
938 919
939 Object* KeyedStoreIC::Store(Handle<Object> object, 920 Object* KeyedStoreIC::Store(State state,
921 Handle<Object> object,
940 Handle<Object> key, 922 Handle<Object> key,
941 Handle<Object> value) { 923 Handle<Object> value) {
942 if (key->IsSymbol()) { 924 if (key->IsSymbol()) {
943 Handle<String> name = Handle<String>::cast(key); 925 Handle<String> name = Handle<String>::cast(key);
944 926
945 // If the object is undefined or null it's illegal to try to set any 927 // If the object is undefined or null it's illegal to try to set any
946 // properties on it; throw a TypeError in that case. 928 // properties on it; throw a TypeError in that case.
947 if (object->IsUndefined() || object->IsNull()) { 929 if (object->IsUndefined() || object->IsNull()) {
948 return TypeError("non_object_property_store", object, name); 930 return TypeError("non_object_property_store", object, name);
949 } 931 }
(...skipping 10 matching lines...) Expand all
960 if (result.is_null()) return Failure::Exception(); 942 if (result.is_null()) return Failure::Exception();
961 return *value; 943 return *value;
962 } 944 }
963 945
964 // Lookup the property locally in the receiver. 946 // Lookup the property locally in the receiver.
965 LookupResult lookup; 947 LookupResult lookup;
966 receiver->LocalLookup(*name, &lookup); 948 receiver->LocalLookup(*name, &lookup);
967 949
968 // Update inline cache and stub cache. 950 // Update inline cache and stub cache.
969 if (FLAG_use_ic && lookup.IsLoaded()) { 951 if (FLAG_use_ic && lookup.IsLoaded()) {
970 UpdateCaches(&lookup, receiver, name, value); 952 UpdateCaches(&lookup, state, receiver, name, value);
971 } 953 }
972 954
973 // Set the property. 955 // Set the property.
974 return receiver->SetProperty(*name, *value, NONE); 956 return receiver->SetProperty(*name, *value, NONE);
975 } 957 }
976 958
977 // Do not use ICs for objects that require access checks (including 959 // Do not use ICs for objects that require access checks (including
978 // the global object). 960 // the global object).
979 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 961 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
980 962
981 if (use_ic) set_target(generic_stub()); 963 if (use_ic) set_target(generic_stub());
982 964
983 // Set the property. 965 // Set the property.
984 return Runtime::SetObjectProperty(object, key, value, NONE); 966 return Runtime::SetObjectProperty(object, key, value, NONE);
985 } 967 }
986 968
987 969
988 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 970 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
971 State state,
989 Handle<JSObject> receiver, 972 Handle<JSObject> receiver,
990 Handle<String> name, 973 Handle<String> name,
991 Handle<Object> value) { 974 Handle<Object> value) {
992 ASSERT(lookup->IsLoaded()); 975 ASSERT(lookup->IsLoaded());
993 // Bail out if we didn't find a result. 976 // Bail out if we didn't find a result.
994 if (!lookup->IsValid() || !lookup->IsCacheable()) return; 977 if (!lookup->IsValid() || !lookup->IsCacheable()) return;
995 978
996 // If the property is read-only, we leave the IC in its current 979 // If the property is read-only, we leave the IC in its current
997 // state. 980 // state.
998 if (lookup->IsReadOnly()) return; 981 if (lookup->IsReadOnly()) return;
999 982
1000 // If the property has a non-field type allowing map transitions 983 // If the property has a non-field type allowing map transitions
1001 // where there is extra room in the object, we leave the IC in its 984 // where there is extra room in the object, we leave the IC in its
1002 // current state. 985 // current state.
1003 PropertyType type = lookup->type(); 986 PropertyType type = lookup->type();
1004 987
1005 // Compute the code stub for this store; used for rewriting to 988 // Compute the code stub for this store; used for rewriting to
1006 // monomorphic state and making sure that the code stub is in the 989 // monomorphic state and making sure that the code stub is in the
1007 // stub cache. 990 // stub cache.
1008 Object* code = Heap::undefined_value(); 991 Object* code = NULL;
1009 State state = ComputeCacheState(target(), *receiver, *name, &code);
1010 992
1011 switch (type) { 993 switch (type) {
1012 case FIELD: { 994 case FIELD: {
1013 code = StubCache::ComputeKeyedStoreField(*name, *receiver, 995 code = StubCache::ComputeKeyedStoreField(*name, *receiver,
1014 lookup->GetFieldIndex()); 996 lookup->GetFieldIndex());
1015 break; 997 break;
1016 } 998 }
1017 case MAP_TRANSITION: { 999 case MAP_TRANSITION: {
1018 if (lookup->GetAttributes() == NONE) { 1000 if (lookup->GetAttributes() == NONE) {
1019 if (receiver->map()->unused_property_fields() == 0) return; 1001 if (receiver->map()->unused_property_fields() == 0) return;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 1039
1058 // ---------------------------------------------------------------------------- 1040 // ----------------------------------------------------------------------------
1059 // Static IC stub generators. 1041 // Static IC stub generators.
1060 // 1042 //
1061 1043
1062 // Used from ic_<arch>.cc. 1044 // Used from ic_<arch>.cc.
1063 Object* CallIC_Miss(Arguments args) { 1045 Object* CallIC_Miss(Arguments args) {
1064 NoHandleAllocation na; 1046 NoHandleAllocation na;
1065 ASSERT(args.length() == 2); 1047 ASSERT(args.length() == 2);
1066 CallIC ic; 1048 CallIC ic;
1067 return ic.LoadFunction(args.at<Object>(0), args.at<String>(1)); 1049 IC::State state = IC::StateFrom(ic.target(), args[0]);
1050 return ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
1068 } 1051 }
1069 1052
1070 1053
1071 void CallIC::GenerateInitialize(MacroAssembler* masm, int argc) { 1054 void CallIC::GenerateInitialize(MacroAssembler* masm, int argc) {
1072 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); 1055 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
1073 } 1056 }
1074 1057
1075 1058
1076 void CallIC::GeneratePreMonomorphic(MacroAssembler* masm, int argc) { 1059 void CallIC::GeneratePreMonomorphic(MacroAssembler* masm, int argc) {
1077 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); 1060 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
1078 } 1061 }
1079 1062
1080 1063
1081 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1064 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1082 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); 1065 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
1083 } 1066 }
1084 1067
1085 1068
1086 // Used from ic_<arch>.cc. 1069 // Used from ic_<arch>.cc.
1087 Object* LoadIC_Miss(Arguments args) { 1070 Object* LoadIC_Miss(Arguments args) {
1088 NoHandleAllocation na; 1071 NoHandleAllocation na;
1089 ASSERT(args.length() == 2); 1072 ASSERT(args.length() == 2);
1090 LoadIC ic; 1073 LoadIC ic;
1091 return ic.Load(args.at<Object>(0), args.at<String>(1)); 1074 IC::State state = IC::StateFrom(ic.target(), args[0]);
1075 return ic.Load(state, args.at<Object>(0), args.at<String>(1));
1092 } 1076 }
1093 1077
1094 1078
1095 void LoadIC::GenerateInitialize(MacroAssembler* masm) { 1079 void LoadIC::GenerateInitialize(MacroAssembler* masm) {
1096 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); 1080 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
1097 } 1081 }
1098 1082
1099 1083
1100 void LoadIC::GeneratePreMonomorphic(MacroAssembler* masm) { 1084 void LoadIC::GeneratePreMonomorphic(MacroAssembler* masm) {
1101 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); 1085 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
1102 } 1086 }
1103 1087
1104 1088
1105 // Used from ic_<arch>.cc 1089 // Used from ic_<arch>.cc
1106 Object* KeyedLoadIC_Miss(Arguments args) { 1090 Object* KeyedLoadIC_Miss(Arguments args) {
1107 NoHandleAllocation na; 1091 NoHandleAllocation na;
1108 ASSERT(args.length() == 2); 1092 ASSERT(args.length() == 2);
1109 KeyedLoadIC ic; 1093 KeyedLoadIC ic;
1110 return ic.Load(args.at<Object>(0), args.at<Object>(1)); 1094 IC::State state = IC::StateFrom(ic.target(), args[0]);
1095 return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
1111 } 1096 }
1112 1097
1113 1098
1114 void KeyedLoadIC::GenerateInitialize(MacroAssembler* masm) { 1099 void KeyedLoadIC::GenerateInitialize(MacroAssembler* masm) {
1115 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss))); 1100 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
1116 } 1101 }
1117 1102
1118 1103
1119 void KeyedLoadIC::GeneratePreMonomorphic(MacroAssembler* masm) { 1104 void KeyedLoadIC::GeneratePreMonomorphic(MacroAssembler* masm) {
1120 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss))); 1105 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
1121 } 1106 }
1122 1107
1123 1108
1124 // Used from ic_<arch>.cc. 1109 // Used from ic_<arch>.cc.
1125 Object* StoreIC_Miss(Arguments args) { 1110 Object* StoreIC_Miss(Arguments args) {
1126 NoHandleAllocation na; 1111 NoHandleAllocation na;
1127 ASSERT(args.length() == 3); 1112 ASSERT(args.length() == 3);
1128 StoreIC ic; 1113 StoreIC ic;
1129 return ic.Store(args.at<Object>(0), args.at<String>(1), args.at<Object>(2)); 1114 IC::State state = IC::StateFrom(ic.target(), args[0]);
1115 return ic.Store(state, args.at<Object>(0), args.at<String>(1),
1116 args.at<Object>(2));
1130 } 1117 }
1131 1118
1132 1119
1133 void StoreIC::GenerateInitialize(MacroAssembler* masm) { 1120 void StoreIC::GenerateInitialize(MacroAssembler* masm) {
1134 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); 1121 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
1135 } 1122 }
1136 1123
1137 1124
1138 void StoreIC::GenerateMiss(MacroAssembler* masm) { 1125 void StoreIC::GenerateMiss(MacroAssembler* masm) {
1139 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); 1126 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
1140 } 1127 }
1141 1128
1142 1129
1143 // Used from ic_<arch>.cc. 1130 // Used from ic_<arch>.cc.
1144 Object* KeyedStoreIC_Miss(Arguments args) { 1131 Object* KeyedStoreIC_Miss(Arguments args) {
1145 NoHandleAllocation na; 1132 NoHandleAllocation na;
1146 ASSERT(args.length() == 3); 1133 ASSERT(args.length() == 3);
1147 KeyedStoreIC ic; 1134 KeyedStoreIC ic;
1148 return ic.Store(args.at<Object>(0), args.at<Object>(1), args.at<Object>(2)); 1135 IC::State state = IC::StateFrom(ic.target(), args[0]);
1136 return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
1137 args.at<Object>(2));
1149 } 1138 }
1150 1139
1151 1140
1152 void KeyedStoreIC::GenerateInitialize(MacroAssembler* masm) { 1141 void KeyedStoreIC::GenerateInitialize(MacroAssembler* masm) {
1153 Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss))); 1142 Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss)));
1154 } 1143 }
1155 1144
1156 1145
1157 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 1146 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
1158 Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss))); 1147 Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss)));
1159 } 1148 }
1160 1149
1161 1150
1162 static Address IC_utilities[] = { 1151 static Address IC_utilities[] = {
1163 #define ADDR(name) FUNCTION_ADDR(name), 1152 #define ADDR(name) FUNCTION_ADDR(name),
1164 IC_UTIL_LIST(ADDR) 1153 IC_UTIL_LIST(ADDR)
1165 NULL 1154 NULL
1166 #undef ADDR 1155 #undef ADDR
1167 }; 1156 };
1168 1157
1169 1158
1170 Address IC::AddressFromUtilityId(IC::UtilityId id) { 1159 Address IC::AddressFromUtilityId(IC::UtilityId id) {
1171 return IC_utilities[id]; 1160 return IC_utilities[id];
1172 } 1161 }
1173 1162
1174 1163
1175 } } // namespace v8::internal 1164 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698