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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 return 0; | 58 return 0; |
59 } | 59 } |
60 | 60 |
61 void IC::TraceIC(const char* type, | 61 void IC::TraceIC(const char* type, |
62 Handle<Object> name, | 62 Handle<Object> name, |
63 State old_state, | 63 State old_state, |
64 Code* new_target, | 64 Code* new_target, |
65 const char* extra_info) { | 65 const char* extra_info) { |
66 if (FLAG_trace_ic) { | 66 if (FLAG_trace_ic) { |
67 State new_state = StateFrom(new_target, | 67 State new_state = StateFrom(new_target, |
68 Heap::undefined_value(), | 68 HEAP->undefined_value(), |
69 Heap::undefined_value()); | 69 HEAP->undefined_value()); |
70 PrintF("[%s (%c->%c)%s", type, | 70 PrintF("[%s (%c->%c)%s", type, |
71 TransitionMarkFromState(old_state), | 71 TransitionMarkFromState(old_state), |
72 TransitionMarkFromState(new_state), | 72 TransitionMarkFromState(new_state), |
73 extra_info); | 73 extra_info); |
74 name->Print(); | 74 name->Print(); |
75 PrintF("]\n"); | 75 PrintF("]\n"); |
76 } | 76 } |
77 } | 77 } |
78 #endif | 78 #endif |
79 | 79 |
80 | 80 |
81 IC::IC(FrameDepth depth) { | 81 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
| 82 ASSERT(isolate == Isolate::Current()); |
82 // To improve the performance of the (much used) IC code, we unfold | 83 // To improve the performance of the (much used) IC code, we unfold |
83 // a few levels of the stack frame iteration code. This yields a | 84 // a few levels of the stack frame iteration code. This yields a |
84 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. | 85 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. |
85 const Address entry = Top::c_entry_fp(Top::GetCurrentThread()); | 86 const Address entry = |
| 87 Isolate::c_entry_fp(isolate->thread_local_top()); |
86 Address* pc_address = | 88 Address* pc_address = |
87 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 89 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); |
88 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 90 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
89 // If there's another JavaScript frame on the stack, we need to look | 91 // If there's another JavaScript frame on the stack, we need to look |
90 // one frame further down the stack to find the frame pointer and | 92 // one frame further down the stack to find the frame pointer and |
91 // the return address stack slot. | 93 // the return address stack slot. |
92 if (depth == EXTRA_CALL_FRAME) { | 94 if (depth == EXTRA_CALL_FRAME) { |
93 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 95 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; |
94 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 96 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); |
95 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 97 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 // Return the address in the original code. This is the place where | 131 // Return the address in the original code. This is the place where |
130 // the call which has been overwritten by the DebugBreakXXX resides | 132 // the call which has been overwritten by the DebugBreakXXX resides |
131 // and the place where the inline cache system should look. | 133 // and the place where the inline cache system should look. |
132 intptr_t delta = | 134 intptr_t delta = |
133 original_code->instruction_start() - code->instruction_start(); | 135 original_code->instruction_start() - code->instruction_start(); |
134 return addr + delta; | 136 return addr + delta; |
135 } | 137 } |
136 #endif | 138 #endif |
137 | 139 |
138 | 140 |
139 static bool HasNormalObjectsInPrototypeChain(LookupResult* lookup, | 141 static bool HasNormalObjectsInPrototypeChain(Isolate* isolate, |
| 142 LookupResult* lookup, |
140 Object* receiver) { | 143 Object* receiver) { |
141 Object* end = lookup->IsProperty() ? lookup->holder() : Heap::null_value(); | 144 Object* end = lookup->IsProperty() |
| 145 ? lookup->holder() : isolate->heap()->null_value(); |
142 for (Object* current = receiver; | 146 for (Object* current = receiver; |
143 current != end; | 147 current != end; |
144 current = current->GetPrototype()) { | 148 current = current->GetPrototype()) { |
145 if (current->IsJSObject() && | 149 if (current->IsJSObject() && |
146 !JSObject::cast(current)->HasFastProperties() && | 150 !JSObject::cast(current)->HasFastProperties() && |
147 !current->IsJSGlobalProxy() && | 151 !current->IsJSGlobalProxy() && |
148 !current->IsJSGlobalObject()) { | 152 !current->IsJSGlobalObject()) { |
149 return true; | 153 return true; |
150 } | 154 } |
151 } | 155 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 if (receiver->IsJSBuiltinsObject()) { | 228 if (receiver->IsJSBuiltinsObject()) { |
225 return UNINITIALIZED; | 229 return UNINITIALIZED; |
226 } | 230 } |
227 | 231 |
228 return MONOMORPHIC; | 232 return MONOMORPHIC; |
229 } | 233 } |
230 | 234 |
231 | 235 |
232 RelocInfo::Mode IC::ComputeMode() { | 236 RelocInfo::Mode IC::ComputeMode() { |
233 Address addr = address(); | 237 Address addr = address(); |
234 Code* code = Code::cast(Heap::FindCodeObject(addr)); | 238 Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr)); |
235 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); | 239 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); |
236 !it.done(); it.next()) { | 240 !it.done(); it.next()) { |
237 RelocInfo* info = it.rinfo(); | 241 RelocInfo* info = it.rinfo(); |
238 if (info->pc() == addr) return info->rmode(); | 242 if (info->pc() == addr) return info->rmode(); |
239 } | 243 } |
240 UNREACHABLE(); | 244 UNREACHABLE(); |
241 return RelocInfo::NONE; | 245 return RelocInfo::NONE; |
242 } | 246 } |
243 | 247 |
244 | 248 |
245 Failure* IC::TypeError(const char* type, | 249 Failure* IC::TypeError(const char* type, |
246 Handle<Object> object, | 250 Handle<Object> object, |
247 Handle<Object> key) { | 251 Handle<Object> key) { |
248 HandleScope scope; | 252 HandleScope scope(isolate()); |
249 Handle<Object> args[2] = { key, object }; | 253 Handle<Object> args[2] = { key, object }; |
250 Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2)); | 254 Handle<Object> error = isolate()->factory()->NewTypeError( |
251 return Top::Throw(*error); | 255 type, HandleVector(args, 2)); |
| 256 return isolate()->Throw(*error); |
252 } | 257 } |
253 | 258 |
254 | 259 |
255 Failure* IC::ReferenceError(const char* type, Handle<String> name) { | 260 Failure* IC::ReferenceError(const char* type, Handle<String> name) { |
256 HandleScope scope; | 261 HandleScope scope(isolate()); |
257 Handle<Object> error = | 262 Handle<Object> error = isolate()->factory()->NewReferenceError( |
258 Factory::NewReferenceError(type, HandleVector(&name, 1)); | 263 type, HandleVector(&name, 1)); |
259 return Top::Throw(*error); | 264 return isolate()->Throw(*error); |
260 } | 265 } |
261 | 266 |
262 | 267 |
263 void IC::Clear(Address address) { | 268 void IC::Clear(Address address) { |
264 Code* target = GetTargetAtAddress(address); | 269 Code* target = GetTargetAtAddress(address); |
265 | 270 |
266 // Don't clear debug break inline cache as it will remove the break point. | 271 // Don't clear debug break inline cache as it will remove the break point. |
267 if (target->ic_state() == DEBUG_BREAK) return; | 272 if (target->ic_state() == DEBUG_BREAK) return; |
268 | 273 |
269 switch (target->kind()) { | 274 switch (target->kind()) { |
(...skipping 15 matching lines...) Expand all Loading... |
285 return; | 290 return; |
286 default: UNREACHABLE(); | 291 default: UNREACHABLE(); |
287 } | 292 } |
288 } | 293 } |
289 | 294 |
290 | 295 |
291 void CallICBase::Clear(Address address, Code* target) { | 296 void CallICBase::Clear(Address address, Code* target) { |
292 State state = target->ic_state(); | 297 State state = target->ic_state(); |
293 if (state == UNINITIALIZED) return; | 298 if (state == UNINITIALIZED) return; |
294 Code* code = | 299 Code* code = |
295 StubCache::FindCallInitialize(target->arguments_count(), | 300 Isolate::Current()->stub_cache()->FindCallInitialize( |
296 target->ic_in_loop(), | 301 target->arguments_count(), |
297 target->kind()); | 302 target->ic_in_loop(), |
| 303 target->kind()); |
298 SetTargetAtAddress(address, code); | 304 SetTargetAtAddress(address, code); |
299 } | 305 } |
300 | 306 |
301 | 307 |
302 void KeyedLoadIC::ClearInlinedVersion(Address address) { | 308 void KeyedLoadIC::ClearInlinedVersion(Address address) { |
303 // Insert null as the map to check for to make sure the map check fails | 309 // Insert null as the map to check for to make sure the map check fails |
304 // sending control flow to the IC instead of the inlined version. | 310 // sending control flow to the IC instead of the inlined version. |
305 PatchInlinedLoad(address, Heap::null_value()); | 311 PatchInlinedLoad(address, HEAP->null_value()); |
306 } | 312 } |
307 | 313 |
308 | 314 |
309 void KeyedLoadIC::Clear(Address address, Code* target) { | 315 void KeyedLoadIC::Clear(Address address, Code* target) { |
310 if (target->ic_state() == UNINITIALIZED) return; | 316 if (target->ic_state() == UNINITIALIZED) return; |
311 // Make sure to also clear the map used in inline fast cases. If we | 317 // Make sure to also clear the map used in inline fast cases. If we |
312 // do not clear these maps, cached code can keep objects alive | 318 // do not clear these maps, cached code can keep objects alive |
313 // through the embedded maps. | 319 // through the embedded maps. |
314 ClearInlinedVersion(address); | 320 ClearInlinedVersion(address); |
315 SetTargetAtAddress(address, initialize_stub()); | 321 SetTargetAtAddress(address, initialize_stub()); |
316 } | 322 } |
317 | 323 |
318 | 324 |
319 void LoadIC::ClearInlinedVersion(Address address) { | 325 void LoadIC::ClearInlinedVersion(Address address) { |
320 // Reset the map check of the inlined inobject property load (if | 326 // Reset the map check of the inlined inobject property load (if |
321 // present) to guarantee failure by holding an invalid map (the null | 327 // present) to guarantee failure by holding an invalid map (the null |
322 // value). The offset can be patched to anything. | 328 // value). The offset can be patched to anything. |
323 PatchInlinedLoad(address, Heap::null_value(), 0); | 329 Heap* heap = HEAP; |
| 330 PatchInlinedLoad(address, heap->null_value(), 0); |
324 PatchInlinedContextualLoad(address, | 331 PatchInlinedContextualLoad(address, |
325 Heap::null_value(), | 332 heap->null_value(), |
326 Heap::null_value(), | 333 heap->null_value(), |
327 true); | 334 true); |
328 } | 335 } |
329 | 336 |
330 | 337 |
331 void LoadIC::Clear(Address address, Code* target) { | 338 void LoadIC::Clear(Address address, Code* target) { |
332 if (target->ic_state() == UNINITIALIZED) return; | 339 if (target->ic_state() == UNINITIALIZED) return; |
333 ClearInlinedVersion(address); | 340 ClearInlinedVersion(address); |
334 SetTargetAtAddress(address, initialize_stub()); | 341 SetTargetAtAddress(address, initialize_stub()); |
335 } | 342 } |
336 | 343 |
337 | 344 |
338 void StoreIC::ClearInlinedVersion(Address address) { | 345 void StoreIC::ClearInlinedVersion(Address address) { |
339 // Reset the map check of the inlined inobject property store (if | 346 // Reset the map check of the inlined inobject property store (if |
340 // present) to guarantee failure by holding an invalid map (the null | 347 // present) to guarantee failure by holding an invalid map (the null |
341 // value). The offset can be patched to anything. | 348 // value). The offset can be patched to anything. |
342 PatchInlinedStore(address, Heap::null_value(), 0); | 349 PatchInlinedStore(address, HEAP->null_value(), 0); |
343 } | 350 } |
344 | 351 |
345 | 352 |
346 void StoreIC::Clear(Address address, Code* target) { | 353 void StoreIC::Clear(Address address, Code* target) { |
347 if (target->ic_state() == UNINITIALIZED) return; | 354 if (target->ic_state() == UNINITIALIZED) return; |
348 ClearInlinedVersion(address); | 355 ClearInlinedVersion(address); |
349 SetTargetAtAddress(address, | 356 SetTargetAtAddress(address, |
350 (target->extra_ic_state() == kStrictMode) | 357 (target->extra_ic_state() == kStrictMode) |
351 ? initialize_stub_strict() | 358 ? initialize_stub_strict() |
352 : initialize_stub()); | 359 : initialize_stub()); |
353 } | 360 } |
354 | 361 |
355 | 362 |
356 void KeyedStoreIC::ClearInlinedVersion(Address address) { | 363 void KeyedStoreIC::ClearInlinedVersion(Address address) { |
357 // Insert null as the elements map to check for. This will make | 364 // Insert null as the elements map to check for. This will make |
358 // sure that the elements fast-case map check fails so that control | 365 // sure that the elements fast-case map check fails so that control |
359 // flows to the IC instead of the inlined version. | 366 // flows to the IC instead of the inlined version. |
360 PatchInlinedStore(address, Heap::null_value()); | 367 PatchInlinedStore(address, HEAP->null_value()); |
361 } | 368 } |
362 | 369 |
363 | 370 |
364 void KeyedStoreIC::RestoreInlinedVersion(Address address) { | 371 void KeyedStoreIC::RestoreInlinedVersion(Address address) { |
365 // Restore the fast-case elements map check so that the inlined | 372 // Restore the fast-case elements map check so that the inlined |
366 // version can be used again. | 373 // version can be used again. |
367 PatchInlinedStore(address, Heap::fixed_array_map()); | 374 PatchInlinedStore(address, HEAP->fixed_array_map()); |
368 } | 375 } |
369 | 376 |
370 | 377 |
371 void KeyedStoreIC::Clear(Address address, Code* target) { | 378 void KeyedStoreIC::Clear(Address address, Code* target) { |
372 if (target->ic_state() == UNINITIALIZED) return; | 379 if (target->ic_state() == UNINITIALIZED) return; |
373 SetTargetAtAddress(address, | 380 SetTargetAtAddress(address, |
374 (target->extra_ic_state() == kStrictMode) | 381 (target->extra_ic_state() == kStrictMode) |
375 ? initialize_stub_strict() | 382 ? initialize_stub_strict() |
376 : initialize_stub()); | 383 : initialize_stub()); |
377 } | 384 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 lookup->NotFound(); | 423 lookup->NotFound(); |
417 return; | 424 return; |
418 } | 425 } |
419 | 426 |
420 object = proto; | 427 object = proto; |
421 } | 428 } |
422 } | 429 } |
423 | 430 |
424 | 431 |
425 Object* CallICBase::TryCallAsFunction(Object* object) { | 432 Object* CallICBase::TryCallAsFunction(Object* object) { |
426 HandleScope scope; | 433 HandleScope scope(isolate()); |
427 Handle<Object> target(object); | 434 Handle<Object> target(object, isolate()); |
428 Handle<Object> delegate = Execution::GetFunctionDelegate(target); | 435 Handle<Object> delegate = Execution::GetFunctionDelegate(target); |
429 | 436 |
430 if (delegate->IsJSFunction()) { | 437 if (delegate->IsJSFunction()) { |
431 // Patch the receiver and use the delegate as the function to | 438 // Patch the receiver and use the delegate as the function to |
432 // invoke. This is used for invoking objects as if they were | 439 // invoke. This is used for invoking objects as if they were |
433 // functions. | 440 // functions. |
434 const int argc = this->target()->arguments_count(); | 441 const int argc = this->target()->arguments_count(); |
435 StackFrameLocator locator; | 442 StackFrameLocator locator; |
436 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 443 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
437 int index = frame->ComputeExpressionsCount() - (argc + 1); | 444 int index = frame->ComputeExpressionsCount() - (argc + 1); |
(...skipping 14 matching lines...) Expand all Loading... |
452 } | 459 } |
453 } | 460 } |
454 | 461 |
455 // And only wrap string, number or boolean. | 462 // And only wrap string, number or boolean. |
456 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 463 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
457 // Change the receiver to the result of calling ToObject on it. | 464 // Change the receiver to the result of calling ToObject on it. |
458 const int argc = this->target()->arguments_count(); | 465 const int argc = this->target()->arguments_count(); |
459 StackFrameLocator locator; | 466 StackFrameLocator locator; |
460 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 467 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
461 int index = frame->ComputeExpressionsCount() - (argc + 1); | 468 int index = frame->ComputeExpressionsCount() - (argc + 1); |
462 frame->SetExpression(index, *Factory::ToObject(object)); | 469 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); |
463 } | 470 } |
464 } | 471 } |
465 | 472 |
466 | 473 |
467 MaybeObject* CallICBase::LoadFunction(State state, | 474 MaybeObject* CallICBase::LoadFunction(State state, |
468 Code::ExtraICState extra_ic_state, | 475 Code::ExtraICState extra_ic_state, |
469 Handle<Object> object, | 476 Handle<Object> object, |
470 Handle<String> name) { | 477 Handle<String> name) { |
471 // If the object is undefined or null it's illegal to try to get any | 478 // If the object is undefined or null it's illegal to try to get any |
472 // of its properties; throw a TypeError in that case. | 479 // of its properties; throw a TypeError in that case. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 if (attr == ABSENT) { | 531 if (attr == ABSENT) { |
525 if (IsContextual(object)) { | 532 if (IsContextual(object)) { |
526 return ReferenceError("not_defined", name); | 533 return ReferenceError("not_defined", name); |
527 } | 534 } |
528 return TypeError("undefined_method", object, name); | 535 return TypeError("undefined_method", object, name); |
529 } | 536 } |
530 } | 537 } |
531 | 538 |
532 ASSERT(!result->IsTheHole()); | 539 ASSERT(!result->IsTheHole()); |
533 | 540 |
534 HandleScope scope; | 541 HandleScope scope(isolate()); |
535 // Wrap result in a handle because ReceiverToObjectIfRequired may allocate | 542 // Wrap result in a handle because ReceiverToObjectIfRequired may allocate |
536 // new object and cause GC. | 543 // new object and cause GC. |
537 Handle<Object> result_handle(result); | 544 Handle<Object> result_handle(result); |
538 // Make receiver an object if the callee requires it. Strict mode or builtin | 545 // Make receiver an object if the callee requires it. Strict mode or builtin |
539 // functions do not wrap the receiver, non-strict functions and objects | 546 // functions do not wrap the receiver, non-strict functions and objects |
540 // called as functions do. | 547 // called as functions do. |
541 ReceiverToObjectIfRequired(result_handle, object); | 548 ReceiverToObjectIfRequired(result_handle, object); |
542 | 549 |
543 if (result_handle->IsJSFunction()) { | 550 if (result_handle->IsJSFunction()) { |
544 #ifdef ENABLE_DEBUGGER_SUPPORT | 551 #ifdef ENABLE_DEBUGGER_SUPPORT |
545 // Handle stepping into a function if step into is active. | 552 // Handle stepping into a function if step into is active. |
546 if (Debug::StepInActive()) { | 553 Debug* debug = isolate()->debug(); |
| 554 if (debug->StepInActive()) { |
547 // Protect the result in a handle as the debugger can allocate and might | 555 // Protect the result in a handle as the debugger can allocate and might |
548 // cause GC. | 556 // cause GC. |
549 Handle<JSFunction> function(JSFunction::cast(*result_handle)); | 557 Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate()); |
550 Debug::HandleStepIn(function, object, fp(), false); | 558 debug->HandleStepIn(function, object, fp(), false); |
551 return *function; | 559 return *function; |
552 } | 560 } |
553 #endif | 561 #endif |
554 | 562 |
555 return *result_handle; | 563 return *result_handle; |
556 } | 564 } |
557 | 565 |
558 // Try to find a suitable function delegate for the object at hand. | 566 // Try to find a suitable function delegate for the object at hand. |
559 result_handle = Handle<Object>(TryCallAsFunction(*result_handle)); | 567 result_handle = Handle<Object>(TryCallAsFunction(*result_handle)); |
560 if (result_handle->IsJSFunction()) return *result_handle; | 568 if (result_handle->IsJSFunction()) return *result_handle; |
561 | 569 |
562 return TypeError("property_not_function", object, name); | 570 return TypeError("property_not_function", object, name); |
563 } | 571 } |
564 | 572 |
565 | 573 |
566 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, | 574 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, |
567 Handle<Object> object, | 575 Handle<Object> object, |
568 Code::ExtraICState* extra_ic_state) { | 576 Code::ExtraICState* extra_ic_state) { |
569 ASSERT(kind_ == Code::CALL_IC); | 577 ASSERT(kind_ == Code::CALL_IC); |
570 if (lookup->type() != CONSTANT_FUNCTION) return false; | 578 if (lookup->type() != CONSTANT_FUNCTION) return false; |
571 JSFunction* function = lookup->GetConstantFunction(); | 579 JSFunction* function = lookup->GetConstantFunction(); |
572 if (!function->shared()->HasBuiltinFunctionId()) return false; | 580 if (!function->shared()->HasBuiltinFunctionId()) return false; |
573 | 581 |
574 // Fetch the arguments passed to the called function. | 582 // Fetch the arguments passed to the called function. |
575 const int argc = target()->arguments_count(); | 583 const int argc = target()->arguments_count(); |
576 Address entry = Top::c_entry_fp(Top::GetCurrentThread()); | 584 Address entry = isolate()->c_entry_fp(isolate()->thread_local_top()); |
577 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 585 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
578 Arguments args(argc + 1, | 586 Arguments args(argc + 1, |
579 &Memory::Object_at(fp + | 587 &Memory::Object_at(fp + |
580 StandardFrameConstants::kCallerSPOffset + | 588 StandardFrameConstants::kCallerSPOffset + |
581 argc * kPointerSize)); | 589 argc * kPointerSize)); |
582 switch (function->shared()->builtin_function_id()) { | 590 switch (function->shared()->builtin_function_id()) { |
583 case kStringCharCodeAt: | 591 case kStringCharCodeAt: |
584 case kStringCharAt: | 592 case kStringCharAt: |
585 if (object->IsString()) { | 593 if (object->IsString()) { |
586 String* string = String::cast(*object); | 594 String* string = String::cast(*object); |
(...skipping 29 matching lines...) Expand all Loading... |
616 State state, | 624 State state, |
617 Code::ExtraICState extra_ic_state, | 625 Code::ExtraICState extra_ic_state, |
618 Handle<Object> object, | 626 Handle<Object> object, |
619 Handle<String> name) { | 627 Handle<String> name) { |
620 int argc = target()->arguments_count(); | 628 int argc = target()->arguments_count(); |
621 InLoopFlag in_loop = target()->ic_in_loop(); | 629 InLoopFlag in_loop = target()->ic_in_loop(); |
622 MaybeObject* maybe_code = NULL; | 630 MaybeObject* maybe_code = NULL; |
623 switch (lookup->type()) { | 631 switch (lookup->type()) { |
624 case FIELD: { | 632 case FIELD: { |
625 int index = lookup->GetFieldIndex(); | 633 int index = lookup->GetFieldIndex(); |
626 maybe_code = StubCache::ComputeCallField(argc, | 634 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, |
627 in_loop, | 635 in_loop, |
628 kind_, | 636 kind_, |
629 *name, | 637 *name, |
630 *object, | 638 *object, |
631 lookup->holder(), | 639 lookup->holder(), |
632 index); | 640 index); |
633 break; | 641 break; |
634 } | 642 } |
635 case CONSTANT_FUNCTION: { | 643 case CONSTANT_FUNCTION: { |
636 // Get the constant function and compute the code stub for this | 644 // Get the constant function and compute the code stub for this |
637 // call; used for rewriting to monomorphic state and making sure | 645 // call; used for rewriting to monomorphic state and making sure |
638 // that the code stub is in the stub cache. | 646 // that the code stub is in the stub cache. |
639 JSFunction* function = lookup->GetConstantFunction(); | 647 JSFunction* function = lookup->GetConstantFunction(); |
640 maybe_code = StubCache::ComputeCallConstant(argc, | 648 maybe_code = |
641 in_loop, | 649 isolate()->stub_cache()->ComputeCallConstant(argc, |
642 kind_, | 650 in_loop, |
643 extra_ic_state, | 651 kind_, |
644 *name, | 652 extra_ic_state, |
645 *object, | 653 *name, |
646 lookup->holder(), | 654 *object, |
647 function); | 655 lookup->holder(), |
| 656 function); |
648 break; | 657 break; |
649 } | 658 } |
650 case NORMAL: { | 659 case NORMAL: { |
651 if (!object->IsJSObject()) return NULL; | 660 if (!object->IsJSObject()) return NULL; |
652 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 661 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
653 | 662 |
654 if (lookup->holder()->IsGlobalObject()) { | 663 if (lookup->holder()->IsGlobalObject()) { |
655 GlobalObject* global = GlobalObject::cast(lookup->holder()); | 664 GlobalObject* global = GlobalObject::cast(lookup->holder()); |
656 JSGlobalPropertyCell* cell = | 665 JSGlobalPropertyCell* cell = |
657 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 666 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); |
658 if (!cell->value()->IsJSFunction()) return NULL; | 667 if (!cell->value()->IsJSFunction()) return NULL; |
659 JSFunction* function = JSFunction::cast(cell->value()); | 668 JSFunction* function = JSFunction::cast(cell->value()); |
660 maybe_code = StubCache::ComputeCallGlobal(argc, | 669 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, |
661 in_loop, | 670 in_loop, |
662 kind_, | 671 kind_, |
663 *name, | 672 *name, |
664 *receiver, | 673 *receiver, |
665 global, | 674 global, |
666 cell, | 675 cell, |
667 function); | 676 function); |
668 } else { | 677 } else { |
669 // There is only one shared stub for calling normalized | 678 // There is only one shared stub for calling normalized |
670 // properties. It does not traverse the prototype chain, so the | 679 // properties. It does not traverse the prototype chain, so the |
671 // property must be found in the receiver for the stub to be | 680 // property must be found in the receiver for the stub to be |
672 // applicable. | 681 // applicable. |
673 if (lookup->holder() != *receiver) return NULL; | 682 if (lookup->holder() != *receiver) return NULL; |
674 maybe_code = StubCache::ComputeCallNormal(argc, | 683 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, |
675 in_loop, | 684 in_loop, |
676 kind_, | 685 kind_, |
677 *name, | 686 *name, |
678 *receiver); | 687 *receiver); |
679 } | 688 } |
680 break; | 689 break; |
681 } | 690 } |
682 case INTERCEPTOR: { | 691 case INTERCEPTOR: { |
683 ASSERT(HasInterceptorGetter(lookup->holder())); | 692 ASSERT(HasInterceptorGetter(lookup->holder())); |
684 maybe_code = StubCache::ComputeCallInterceptor(argc, | 693 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( |
685 kind_, | 694 argc, |
686 *name, | 695 kind_, |
687 *object, | 696 *name, |
688 lookup->holder()); | 697 *object, |
| 698 lookup->holder()); |
689 break; | 699 break; |
690 } | 700 } |
691 default: | 701 default: |
692 maybe_code = NULL; | 702 maybe_code = NULL; |
693 break; | 703 break; |
694 } | 704 } |
695 return maybe_code; | 705 return maybe_code; |
696 } | 706 } |
697 | 707 |
698 | 708 |
699 void CallICBase::UpdateCaches(LookupResult* lookup, | 709 void CallICBase::UpdateCaches(LookupResult* lookup, |
700 State state, | 710 State state, |
701 Code::ExtraICState extra_ic_state, | 711 Code::ExtraICState extra_ic_state, |
702 Handle<Object> object, | 712 Handle<Object> object, |
703 Handle<String> name) { | 713 Handle<String> name) { |
704 // Bail out if we didn't find a result. | 714 // Bail out if we didn't find a result. |
705 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 715 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
706 | 716 |
707 if (lookup->holder() != *object && | 717 if (lookup->holder() != *object && |
708 HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) { | 718 HasNormalObjectsInPrototypeChain( |
| 719 isolate(), lookup, object->GetPrototype())) { |
709 // Suppress optimization for prototype chains with slow properties objects | 720 // Suppress optimization for prototype chains with slow properties objects |
710 // in the middle. | 721 // in the middle. |
711 return; | 722 return; |
712 } | 723 } |
713 | 724 |
714 // Compute the number of arguments. | 725 // Compute the number of arguments. |
715 int argc = target()->arguments_count(); | 726 int argc = target()->arguments_count(); |
716 InLoopFlag in_loop = target()->ic_in_loop(); | 727 InLoopFlag in_loop = target()->ic_in_loop(); |
717 MaybeObject* maybe_code = NULL; | 728 MaybeObject* maybe_code = NULL; |
718 bool had_proto_failure = false; | 729 bool had_proto_failure = false; |
719 if (state == UNINITIALIZED) { | 730 if (state == UNINITIALIZED) { |
720 // This is the first time we execute this inline cache. | 731 // This is the first time we execute this inline cache. |
721 // Set the target to the pre monomorphic stub to delay | 732 // Set the target to the pre monomorphic stub to delay |
722 // setting the monomorphic state. | 733 // setting the monomorphic state. |
723 maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); | 734 maybe_code = isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, |
| 735 in_loop, |
| 736 kind_); |
724 } else if (state == MONOMORPHIC) { | 737 } else if (state == MONOMORPHIC) { |
725 if (kind_ == Code::CALL_IC && | 738 if (kind_ == Code::CALL_IC && |
726 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 739 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
727 maybe_code = ComputeMonomorphicStub(lookup, | 740 maybe_code = ComputeMonomorphicStub(lookup, |
728 state, | 741 state, |
729 extra_ic_state, | 742 extra_ic_state, |
730 object, | 743 object, |
731 name); | 744 name); |
732 } else if (kind_ == Code::CALL_IC && | 745 } else if (kind_ == Code::CALL_IC && |
733 TryRemoveInvalidPrototypeDependentStub(target(), | 746 TryRemoveInvalidPrototypeDependentStub(target(), |
734 *object, | 747 *object, |
735 *name)) { | 748 *name)) { |
736 had_proto_failure = true; | 749 had_proto_failure = true; |
737 maybe_code = ComputeMonomorphicStub(lookup, | 750 maybe_code = ComputeMonomorphicStub(lookup, |
738 state, | 751 state, |
739 extra_ic_state, | 752 extra_ic_state, |
740 object, | 753 object, |
741 name); | 754 name); |
742 } else { | 755 } else { |
743 maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); | 756 maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(argc, |
| 757 in_loop, |
| 758 kind_); |
744 } | 759 } |
745 } else { | 760 } else { |
746 maybe_code = ComputeMonomorphicStub(lookup, | 761 maybe_code = ComputeMonomorphicStub(lookup, |
747 state, | 762 state, |
748 extra_ic_state, | 763 extra_ic_state, |
749 object, | 764 object, |
750 name); | 765 name); |
751 } | 766 } |
752 | 767 |
753 // If we're unable to compute the stub (not enough memory left), we | 768 // If we're unable to compute the stub (not enough memory left), we |
754 // simply avoid updating the caches. | 769 // simply avoid updating the caches. |
755 Object* code; | 770 Object* code; |
756 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 771 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; |
757 | 772 |
758 // Patch the call site depending on the state of the cache. | 773 // Patch the call site depending on the state of the cache. |
759 if (state == UNINITIALIZED || | 774 if (state == UNINITIALIZED || |
760 state == PREMONOMORPHIC || | 775 state == PREMONOMORPHIC || |
761 state == MONOMORPHIC || | 776 state == MONOMORPHIC || |
762 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 777 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
763 set_target(Code::cast(code)); | 778 set_target(Code::cast(code)); |
764 } else if (state == MEGAMORPHIC) { | 779 } else if (state == MEGAMORPHIC) { |
765 // Cache code holding map should be consistent with | 780 // Cache code holding map should be consistent with |
766 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 781 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. |
767 Map* map = JSObject::cast(object->IsJSObject() ? *object : | 782 Map* map = JSObject::cast(object->IsJSObject() ? *object : |
768 object->GetPrototype())->map(); | 783 object->GetPrototype())->map(); |
769 | 784 |
770 // Update the stub cache. | 785 // Update the stub cache. |
771 StubCache::Set(*name, map, Code::cast(code)); | 786 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); |
772 } | 787 } |
773 | 788 |
774 USE(had_proto_failure); | 789 USE(had_proto_failure); |
775 #ifdef DEBUG | 790 #ifdef DEBUG |
776 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; | 791 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; |
777 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 792 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
778 name, state, target(), in_loop ? " (in-loop)" : ""); | 793 name, state, target(), in_loop ? " (in-loop)" : ""); |
779 #endif | 794 #endif |
780 } | 795 } |
781 | 796 |
782 | 797 |
783 MaybeObject* KeyedCallIC::LoadFunction(State state, | 798 MaybeObject* KeyedCallIC::LoadFunction(State state, |
784 Handle<Object> object, | 799 Handle<Object> object, |
785 Handle<Object> key) { | 800 Handle<Object> key) { |
786 if (key->IsSymbol()) { | 801 if (key->IsSymbol()) { |
787 return CallICBase::LoadFunction(state, | 802 return CallICBase::LoadFunction(state, |
788 Code::kNoExtraICState, | 803 Code::kNoExtraICState, |
789 object, | 804 object, |
790 Handle<String>::cast(key)); | 805 Handle<String>::cast(key)); |
791 } | 806 } |
792 | 807 |
793 if (object->IsUndefined() || object->IsNull()) { | 808 if (object->IsUndefined() || object->IsNull()) { |
794 return TypeError("non_object_property_call", object, key); | 809 return TypeError("non_object_property_call", object, key); |
795 } | 810 } |
796 | 811 |
797 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { | 812 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { |
798 int argc = target()->arguments_count(); | 813 int argc = target()->arguments_count(); |
799 InLoopFlag in_loop = target()->ic_in_loop(); | 814 InLoopFlag in_loop = target()->ic_in_loop(); |
800 MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( | 815 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( |
801 argc, in_loop, Code::KEYED_CALL_IC); | 816 argc, in_loop, Code::KEYED_CALL_IC); |
802 Object* code; | 817 Object* code; |
803 if (maybe_code->ToObject(&code)) { | 818 if (maybe_code->ToObject(&code)) { |
804 set_target(Code::cast(code)); | 819 set_target(Code::cast(code)); |
805 #ifdef DEBUG | 820 #ifdef DEBUG |
806 TraceIC( | 821 TraceIC( |
807 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); | 822 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); |
808 #endif | 823 #endif |
809 } | 824 } |
810 } | 825 } |
811 | 826 |
812 HandleScope scope; | 827 HandleScope scope(isolate()); |
813 Handle<Object> result = GetProperty(object, key); | 828 Handle<Object> result = GetProperty(object, key); |
814 RETURN_IF_EMPTY_HANDLE(result); | 829 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
815 | 830 |
816 // Make receiver an object if the callee requires it. Strict mode or builtin | 831 // Make receiver an object if the callee requires it. Strict mode or builtin |
817 // functions do not wrap the receiver, non-strict functions and objects | 832 // functions do not wrap the receiver, non-strict functions and objects |
818 // called as functions do. | 833 // called as functions do. |
819 ReceiverToObjectIfRequired(result, object); | 834 ReceiverToObjectIfRequired(result, object); |
820 | 835 |
821 if (result->IsJSFunction()) return *result; | 836 if (result->IsJSFunction()) return *result; |
822 result = Handle<Object>(TryCallAsFunction(*result)); | 837 result = Handle<Object>(TryCallAsFunction(*result)); |
823 if (result->IsJSFunction()) return *result; | 838 if (result->IsJSFunction()) return *result; |
824 | 839 |
(...skipping 20 matching lines...) Expand all Loading... |
845 | 860 |
846 if (FLAG_use_ic) { | 861 if (FLAG_use_ic) { |
847 Code* non_monomorphic_stub = | 862 Code* non_monomorphic_stub = |
848 (state == UNINITIALIZED) ? pre_monomorphic_stub() : megamorphic_stub(); | 863 (state == UNINITIALIZED) ? pre_monomorphic_stub() : megamorphic_stub(); |
849 | 864 |
850 // Use specialized code for getting the length of strings and | 865 // Use specialized code for getting the length of strings and |
851 // string wrapper objects. The length property of string wrapper | 866 // string wrapper objects. The length property of string wrapper |
852 // objects is read-only and therefore always returns the length of | 867 // objects is read-only and therefore always returns the length of |
853 // the underlying string value. See ECMA-262 15.5.5.1. | 868 // the underlying string value. See ECMA-262 15.5.5.1. |
854 if ((object->IsString() || object->IsStringWrapper()) && | 869 if ((object->IsString() || object->IsStringWrapper()) && |
855 name->Equals(Heap::length_symbol())) { | 870 name->Equals(isolate()->heap()->length_symbol())) { |
856 HandleScope scope; | 871 HandleScope scope(isolate()); |
857 #ifdef DEBUG | 872 #ifdef DEBUG |
858 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 873 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); |
859 #endif | 874 #endif |
860 if (state == PREMONOMORPHIC) { | 875 if (state == PREMONOMORPHIC) { |
861 if (object->IsString()) { | 876 if (object->IsString()) { |
862 Map* map = HeapObject::cast(*object)->map(); | 877 Map* map = HeapObject::cast(*object)->map(); |
863 const int offset = String::kLengthOffset; | 878 const int offset = String::kLengthOffset; |
864 PatchInlinedLoad(address(), map, offset); | 879 PatchInlinedLoad(address(), map, offset); |
865 set_target(Builtins::builtin(Builtins::LoadIC_StringLength)); | 880 set_target(isolate()->builtins()->builtin( |
| 881 Builtins::LoadIC_StringLength)); |
866 } else { | 882 } else { |
867 set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength)); | 883 set_target(isolate()->builtins()->builtin( |
| 884 Builtins::LoadIC_StringWrapperLength)); |
868 } | 885 } |
869 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | 886 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { |
870 set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength)); | 887 set_target(isolate()->builtins()->builtin( |
| 888 Builtins::LoadIC_StringWrapperLength)); |
871 } else { | 889 } else { |
872 set_target(non_monomorphic_stub); | 890 set_target(non_monomorphic_stub); |
873 } | 891 } |
874 // Get the string if we have a string wrapper object. | 892 // Get the string if we have a string wrapper object. |
875 if (object->IsJSValue()) { | 893 if (object->IsJSValue()) { |
876 object = Handle<Object>(Handle<JSValue>::cast(object)->value()); | 894 object = Handle<Object>(Handle<JSValue>::cast(object)->value(), |
| 895 isolate()); |
877 } | 896 } |
878 return Smi::FromInt(String::cast(*object)->length()); | 897 return Smi::FromInt(String::cast(*object)->length()); |
879 } | 898 } |
880 | 899 |
881 // Use specialized code for getting the length of arrays. | 900 // Use specialized code for getting the length of arrays. |
882 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { | 901 if (object->IsJSArray() && |
| 902 name->Equals(isolate()->heap()->length_symbol())) { |
883 #ifdef DEBUG | 903 #ifdef DEBUG |
884 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | 904 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); |
885 #endif | 905 #endif |
886 if (state == PREMONOMORPHIC) { | 906 if (state == PREMONOMORPHIC) { |
887 Map* map = HeapObject::cast(*object)->map(); | 907 Map* map = HeapObject::cast(*object)->map(); |
888 const int offset = JSArray::kLengthOffset; | 908 const int offset = JSArray::kLengthOffset; |
889 PatchInlinedLoad(address(), map, offset); | 909 PatchInlinedLoad(address(), map, offset); |
890 set_target(Builtins::builtin(Builtins::LoadIC_ArrayLength)); | 910 set_target(isolate()->builtins()->builtin( |
| 911 Builtins::LoadIC_ArrayLength)); |
891 } else { | 912 } else { |
892 set_target(non_monomorphic_stub); | 913 set_target(non_monomorphic_stub); |
893 } | 914 } |
894 return JSArray::cast(*object)->length(); | 915 return JSArray::cast(*object)->length(); |
895 } | 916 } |
896 | 917 |
897 // Use specialized code for getting prototype of functions. | 918 // Use specialized code for getting prototype of functions. |
898 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && | 919 if (object->IsJSFunction() && |
| 920 name->Equals(isolate()->heap()->prototype_symbol()) && |
899 JSFunction::cast(*object)->should_have_prototype()) { | 921 JSFunction::cast(*object)->should_have_prototype()) { |
900 #ifdef DEBUG | 922 #ifdef DEBUG |
901 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 923 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
902 #endif | 924 #endif |
903 if (state == PREMONOMORPHIC) { | 925 if (state == PREMONOMORPHIC) { |
904 set_target(Builtins::builtin(Builtins::LoadIC_FunctionPrototype)); | 926 set_target(isolate()->builtins()->builtin( |
| 927 Builtins::LoadIC_FunctionPrototype)); |
905 } else { | 928 } else { |
906 set_target(non_monomorphic_stub); | 929 set_target(non_monomorphic_stub); |
907 } | 930 } |
908 return Accessors::FunctionGetPrototype(*object, 0); | 931 return Accessors::FunctionGetPrototype(*object, 0); |
909 } | 932 } |
910 } | 933 } |
911 | 934 |
912 // Check if the name is trivially convertible to an index and get | 935 // Check if the name is trivially convertible to an index and get |
913 // the element if so. | 936 // the element if so. |
914 uint32_t index; | 937 uint32_t index; |
915 if (name->AsArrayIndex(&index)) return object->GetElement(index); | 938 if (name->AsArrayIndex(&index)) return object->GetElement(index); |
916 | 939 |
917 // Named lookup in the object. | 940 // Named lookup in the object. |
918 LookupResult lookup; | 941 LookupResult lookup; |
919 LookupForRead(*object, *name, &lookup); | 942 LookupForRead(*object, *name, &lookup); |
920 | 943 |
921 // If we did not find a property, check if we need to throw an exception. | 944 // If we did not find a property, check if we need to throw an exception. |
922 if (!lookup.IsProperty()) { | 945 if (!lookup.IsProperty()) { |
923 if (FLAG_strict || IsContextual(object)) { | 946 if (FLAG_strict || IsContextual(object)) { |
924 return ReferenceError("not_defined", name); | 947 return ReferenceError("not_defined", name); |
925 } | 948 } |
926 LOG(SuspectReadEvent(*name, *object)); | 949 LOG(isolate(), SuspectReadEvent(*name, *object)); |
927 } | 950 } |
928 | 951 |
929 bool can_be_inlined_precheck = | 952 bool can_be_inlined_precheck = |
930 FLAG_use_ic && | 953 FLAG_use_ic && |
931 lookup.IsProperty() && | 954 lookup.IsProperty() && |
932 lookup.IsCacheable() && | 955 lookup.IsCacheable() && |
933 lookup.holder() == *object && | 956 lookup.holder() == *object && |
934 !object->IsAccessCheckNeeded(); | 957 !object->IsAccessCheckNeeded(); |
935 | 958 |
936 bool can_be_inlined = | 959 bool can_be_inlined = |
(...skipping 30 matching lines...) Expand all Loading... |
967 Map* map = lookup.holder()->map(); | 990 Map* map = lookup.holder()->map(); |
968 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast( | 991 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast( |
969 lookup.holder()->property_dictionary()->ValueAt( | 992 lookup.holder()->property_dictionary()->ValueAt( |
970 lookup.GetDictionaryEntry())); | 993 lookup.GetDictionaryEntry())); |
971 if (PatchInlinedContextualLoad(address(), | 994 if (PatchInlinedContextualLoad(address(), |
972 map, | 995 map, |
973 cell, | 996 cell, |
974 lookup.IsDontDelete())) { | 997 lookup.IsDontDelete())) { |
975 set_target(megamorphic_stub()); | 998 set_target(megamorphic_stub()); |
976 TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name); | 999 TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name); |
977 ASSERT(cell->value() != Heap::the_hole_value()); | 1000 ASSERT(cell->value() != isolate()->heap()->the_hole_value()); |
978 return cell->value(); | 1001 return cell->value(); |
979 } | 1002 } |
980 } else { | 1003 } else { |
981 if (FLAG_use_ic && state == PREMONOMORPHIC) { | 1004 if (FLAG_use_ic && state == PREMONOMORPHIC) { |
982 TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inlinable)]\n", name); | 1005 TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inlinable)]\n", name); |
983 } | 1006 } |
984 } | 1007 } |
985 | 1008 |
986 // Update inline cache and stub cache. | 1009 // Update inline cache and stub cache. |
987 if (FLAG_use_ic) { | 1010 if (FLAG_use_ic) { |
(...skipping 26 matching lines...) Expand all Loading... |
1014 Handle<Object> object, | 1037 Handle<Object> object, |
1015 Handle<String> name) { | 1038 Handle<String> name) { |
1016 // Bail out if the result is not cacheable. | 1039 // Bail out if the result is not cacheable. |
1017 if (!lookup->IsCacheable()) return; | 1040 if (!lookup->IsCacheable()) return; |
1018 | 1041 |
1019 // Loading properties from values is not common, so don't try to | 1042 // Loading properties from values is not common, so don't try to |
1020 // deal with non-JS objects here. | 1043 // deal with non-JS objects here. |
1021 if (!object->IsJSObject()) return; | 1044 if (!object->IsJSObject()) return; |
1022 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1045 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1023 | 1046 |
1024 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; | 1047 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; |
1025 | 1048 |
1026 // Compute the code stub for this load. | 1049 // Compute the code stub for this load. |
1027 MaybeObject* maybe_code = NULL; | 1050 MaybeObject* maybe_code = NULL; |
1028 Object* code; | 1051 Object* code; |
1029 if (state == UNINITIALIZED) { | 1052 if (state == UNINITIALIZED) { |
1030 // This is the first time we execute this inline cache. | 1053 // This is the first time we execute this inline cache. |
1031 // Set the target to the pre monomorphic stub to delay | 1054 // Set the target to the pre monomorphic stub to delay |
1032 // setting the monomorphic state. | 1055 // setting the monomorphic state. |
1033 maybe_code = pre_monomorphic_stub(); | 1056 maybe_code = pre_monomorphic_stub(); |
1034 } else if (!lookup->IsProperty()) { | 1057 } else if (!lookup->IsProperty()) { |
1035 // Nonexistent property. The result is undefined. | 1058 // Nonexistent property. The result is undefined. |
1036 maybe_code = StubCache::ComputeLoadNonexistent(*name, *receiver); | 1059 maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name, |
| 1060 *receiver); |
1037 } else { | 1061 } else { |
1038 // Compute monomorphic stub. | 1062 // Compute monomorphic stub. |
1039 switch (lookup->type()) { | 1063 switch (lookup->type()) { |
1040 case FIELD: { | 1064 case FIELD: { |
1041 maybe_code = StubCache::ComputeLoadField(*name, *receiver, | 1065 maybe_code = isolate()->stub_cache()->ComputeLoadField( |
1042 lookup->holder(), | 1066 *name, |
1043 lookup->GetFieldIndex()); | 1067 *receiver, |
| 1068 lookup->holder(), |
| 1069 lookup->GetFieldIndex()); |
1044 break; | 1070 break; |
1045 } | 1071 } |
1046 case CONSTANT_FUNCTION: { | 1072 case CONSTANT_FUNCTION: { |
1047 Object* constant = lookup->GetConstantFunction(); | 1073 Object* constant = lookup->GetConstantFunction(); |
1048 maybe_code = StubCache::ComputeLoadConstant(*name, *receiver, | 1074 maybe_code = isolate()->stub_cache()->ComputeLoadConstant( |
1049 lookup->holder(), constant); | 1075 *name, *receiver, lookup->holder(), constant); |
1050 break; | 1076 break; |
1051 } | 1077 } |
1052 case NORMAL: { | 1078 case NORMAL: { |
1053 if (lookup->holder()->IsGlobalObject()) { | 1079 if (lookup->holder()->IsGlobalObject()) { |
1054 GlobalObject* global = GlobalObject::cast(lookup->holder()); | 1080 GlobalObject* global = GlobalObject::cast(lookup->holder()); |
1055 JSGlobalPropertyCell* cell = | 1081 JSGlobalPropertyCell* cell = |
1056 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 1082 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); |
1057 maybe_code = StubCache::ComputeLoadGlobal(*name, | 1083 maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name, |
1058 *receiver, | 1084 *receiver, |
1059 global, | 1085 global, |
1060 cell, | 1086 cell, |
1061 lookup->IsDontDelete()); | 1087 lookup->IsDontDelete()); |
1062 } else { | 1088 } else { |
1063 // There is only one shared stub for loading normalized | 1089 // There is only one shared stub for loading normalized |
1064 // properties. It does not traverse the prototype chain, so the | 1090 // properties. It does not traverse the prototype chain, so the |
1065 // property must be found in the receiver for the stub to be | 1091 // property must be found in the receiver for the stub to be |
1066 // applicable. | 1092 // applicable. |
1067 if (lookup->holder() != *receiver) return; | 1093 if (lookup->holder() != *receiver) return; |
1068 maybe_code = StubCache::ComputeLoadNormal(); | 1094 maybe_code = isolate()->stub_cache()->ComputeLoadNormal(); |
1069 } | 1095 } |
1070 break; | 1096 break; |
1071 } | 1097 } |
1072 case CALLBACKS: { | 1098 case CALLBACKS: { |
1073 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1099 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; |
1074 AccessorInfo* callback = | 1100 AccessorInfo* callback = |
1075 AccessorInfo::cast(lookup->GetCallbackObject()); | 1101 AccessorInfo::cast(lookup->GetCallbackObject()); |
1076 if (v8::ToCData<Address>(callback->getter()) == 0) return; | 1102 if (v8::ToCData<Address>(callback->getter()) == 0) return; |
1077 maybe_code = StubCache::ComputeLoadCallback(*name, *receiver, | 1103 maybe_code = isolate()->stub_cache()->ComputeLoadCallback( |
1078 lookup->holder(), callback); | 1104 *name, *receiver, lookup->holder(), callback); |
1079 break; | 1105 break; |
1080 } | 1106 } |
1081 case INTERCEPTOR: { | 1107 case INTERCEPTOR: { |
1082 ASSERT(HasInterceptorGetter(lookup->holder())); | 1108 ASSERT(HasInterceptorGetter(lookup->holder())); |
1083 maybe_code = StubCache::ComputeLoadInterceptor(*name, *receiver, | 1109 maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor( |
1084 lookup->holder()); | 1110 *name, *receiver, lookup->holder()); |
1085 break; | 1111 break; |
1086 } | 1112 } |
1087 default: | 1113 default: |
1088 return; | 1114 return; |
1089 } | 1115 } |
1090 } | 1116 } |
1091 | 1117 |
1092 // If we're unable to compute the stub (not enough memory left), we | 1118 // If we're unable to compute the stub (not enough memory left), we |
1093 // simply avoid updating the caches. | 1119 // simply avoid updating the caches. |
1094 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 1120 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; |
1095 | 1121 |
1096 // Patch the call site depending on the state of the cache. | 1122 // Patch the call site depending on the state of the cache. |
1097 if (state == UNINITIALIZED || state == PREMONOMORPHIC || | 1123 if (state == UNINITIALIZED || state == PREMONOMORPHIC || |
1098 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 1124 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
1099 set_target(Code::cast(code)); | 1125 set_target(Code::cast(code)); |
1100 } else if (state == MONOMORPHIC) { | 1126 } else if (state == MONOMORPHIC) { |
1101 set_target(megamorphic_stub()); | 1127 set_target(megamorphic_stub()); |
1102 } else if (state == MEGAMORPHIC) { | 1128 } else if (state == MEGAMORPHIC) { |
1103 // Cache code holding map should be consistent with | 1129 // Cache code holding map should be consistent with |
1104 // GenerateMonomorphicCacheProbe. | 1130 // GenerateMonomorphicCacheProbe. |
1105 Map* map = JSObject::cast(object->IsJSObject() ? *object : | 1131 Map* map = JSObject::cast(object->IsJSObject() ? *object : |
1106 object->GetPrototype())->map(); | 1132 object->GetPrototype())->map(); |
1107 | 1133 |
1108 StubCache::Set(*name, map, Code::cast(code)); | 1134 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); |
1109 } | 1135 } |
1110 | 1136 |
1111 #ifdef DEBUG | 1137 #ifdef DEBUG |
1112 TraceIC("LoadIC", name, state, target()); | 1138 TraceIC("LoadIC", name, state, target()); |
1113 #endif | 1139 #endif |
1114 } | 1140 } |
1115 | 1141 |
1116 | 1142 |
1117 MaybeObject* KeyedLoadIC::Load(State state, | 1143 MaybeObject* KeyedLoadIC::Load(State state, |
1118 Handle<Object> object, | 1144 Handle<Object> object, |
1119 Handle<Object> key) { | 1145 Handle<Object> key) { |
1120 if (key->IsSymbol()) { | 1146 if (key->IsSymbol()) { |
1121 Handle<String> name = Handle<String>::cast(key); | 1147 Handle<String> name = Handle<String>::cast(key); |
1122 | 1148 |
1123 // If the object is undefined or null it's illegal to try to get any | 1149 // If the object is undefined or null it's illegal to try to get any |
1124 // of its properties; throw a TypeError in that case. | 1150 // of its properties; throw a TypeError in that case. |
1125 if (object->IsUndefined() || object->IsNull()) { | 1151 if (object->IsUndefined() || object->IsNull()) { |
1126 return TypeError("non_object_property_load", object, name); | 1152 return TypeError("non_object_property_load", object, name); |
1127 } | 1153 } |
1128 | 1154 |
1129 if (FLAG_use_ic) { | 1155 if (FLAG_use_ic) { |
1130 // TODO(1073): don't ignore the current stub state. | 1156 // TODO(1073): don't ignore the current stub state. |
1131 | 1157 |
1132 // Use specialized code for getting the length of strings. | 1158 // Use specialized code for getting the length of strings. |
1133 if (object->IsString() && name->Equals(Heap::length_symbol())) { | 1159 if (object->IsString() && |
| 1160 name->Equals(isolate()->heap()->length_symbol())) { |
1134 Handle<String> string = Handle<String>::cast(object); | 1161 Handle<String> string = Handle<String>::cast(object); |
1135 Object* code = NULL; | 1162 Object* code = NULL; |
1136 { MaybeObject* maybe_code = | 1163 { MaybeObject* maybe_code = |
1137 StubCache::ComputeKeyedLoadStringLength(*name, *string); | 1164 isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, |
| 1165 *string); |
1138 if (!maybe_code->ToObject(&code)) return maybe_code; | 1166 if (!maybe_code->ToObject(&code)) return maybe_code; |
1139 } | 1167 } |
1140 set_target(Code::cast(code)); | 1168 set_target(Code::cast(code)); |
1141 #ifdef DEBUG | 1169 #ifdef DEBUG |
1142 TraceIC("KeyedLoadIC", name, state, target()); | 1170 TraceIC("KeyedLoadIC", name, state, target()); |
1143 #endif // DEBUG | 1171 #endif // DEBUG |
1144 return Smi::FromInt(string->length()); | 1172 return Smi::FromInt(string->length()); |
1145 } | 1173 } |
1146 | 1174 |
1147 // Use specialized code for getting the length of arrays. | 1175 // Use specialized code for getting the length of arrays. |
1148 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { | 1176 if (object->IsJSArray() && |
| 1177 name->Equals(isolate()->heap()->length_symbol())) { |
1149 Handle<JSArray> array = Handle<JSArray>::cast(object); | 1178 Handle<JSArray> array = Handle<JSArray>::cast(object); |
1150 Object* code; | 1179 Object* code; |
1151 { MaybeObject* maybe_code = | 1180 { MaybeObject* maybe_code = |
1152 StubCache::ComputeKeyedLoadArrayLength(*name, *array); | 1181 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, |
| 1182 *array); |
1153 if (!maybe_code->ToObject(&code)) return maybe_code; | 1183 if (!maybe_code->ToObject(&code)) return maybe_code; |
1154 } | 1184 } |
1155 set_target(Code::cast(code)); | 1185 set_target(Code::cast(code)); |
1156 #ifdef DEBUG | 1186 #ifdef DEBUG |
1157 TraceIC("KeyedLoadIC", name, state, target()); | 1187 TraceIC("KeyedLoadIC", name, state, target()); |
1158 #endif // DEBUG | 1188 #endif // DEBUG |
1159 return JSArray::cast(*object)->length(); | 1189 return JSArray::cast(*object)->length(); |
1160 } | 1190 } |
1161 | 1191 |
1162 // Use specialized code for getting prototype of functions. | 1192 // Use specialized code for getting prototype of functions. |
1163 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && | 1193 if (object->IsJSFunction() && |
| 1194 name->Equals(isolate()->heap()->prototype_symbol()) && |
1164 JSFunction::cast(*object)->should_have_prototype()) { | 1195 JSFunction::cast(*object)->should_have_prototype()) { |
1165 Handle<JSFunction> function = Handle<JSFunction>::cast(object); | 1196 Handle<JSFunction> function = Handle<JSFunction>::cast(object); |
1166 Object* code; | 1197 Object* code; |
1167 { MaybeObject* maybe_code = | 1198 { MaybeObject* maybe_code = |
1168 StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); | 1199 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( |
| 1200 *name, *function); |
1169 if (!maybe_code->ToObject(&code)) return maybe_code; | 1201 if (!maybe_code->ToObject(&code)) return maybe_code; |
1170 } | 1202 } |
1171 set_target(Code::cast(code)); | 1203 set_target(Code::cast(code)); |
1172 #ifdef DEBUG | 1204 #ifdef DEBUG |
1173 TraceIC("KeyedLoadIC", name, state, target()); | 1205 TraceIC("KeyedLoadIC", name, state, target()); |
1174 #endif // DEBUG | 1206 #endif // DEBUG |
1175 return Accessors::FunctionGetPrototype(*object, 0); | 1207 return Accessors::FunctionGetPrototype(*object, 0); |
1176 } | 1208 } |
1177 } | 1209 } |
1178 | 1210 |
1179 // Check if the name is trivially convertible to an index and get | 1211 // Check if the name is trivially convertible to an index and get |
1180 // the element or char if so. | 1212 // the element or char if so. |
1181 uint32_t index = 0; | 1213 uint32_t index = 0; |
1182 if (name->AsArrayIndex(&index)) { | 1214 if (name->AsArrayIndex(&index)) { |
1183 HandleScope scope; | 1215 HandleScope scope(isolate()); |
1184 // Rewrite to the generic keyed load stub. | 1216 // Rewrite to the generic keyed load stub. |
1185 if (FLAG_use_ic) set_target(generic_stub()); | 1217 if (FLAG_use_ic) set_target(generic_stub()); |
1186 return Runtime::GetElementOrCharAt(object, index); | 1218 return Runtime::GetElementOrCharAt(isolate(), object, index); |
1187 } | 1219 } |
1188 | 1220 |
1189 // Named lookup. | 1221 // Named lookup. |
1190 LookupResult lookup; | 1222 LookupResult lookup; |
1191 LookupForRead(*object, *name, &lookup); | 1223 LookupForRead(*object, *name, &lookup); |
1192 | 1224 |
1193 // If we did not find a property, check if we need to throw an exception. | 1225 // If we did not find a property, check if we need to throw an exception. |
1194 if (!lookup.IsProperty()) { | 1226 if (!lookup.IsProperty()) { |
1195 if (FLAG_strict || IsContextual(object)) { | 1227 if (FLAG_strict || IsContextual(object)) { |
1196 return ReferenceError("not_defined", name); | 1228 return ReferenceError("not_defined", name); |
(...skipping 29 matching lines...) Expand all Loading... |
1226 | 1258 |
1227 if (use_ic) { | 1259 if (use_ic) { |
1228 Code* stub = generic_stub(); | 1260 Code* stub = generic_stub(); |
1229 if (state == UNINITIALIZED) { | 1261 if (state == UNINITIALIZED) { |
1230 if (object->IsString() && key->IsNumber()) { | 1262 if (object->IsString() && key->IsNumber()) { |
1231 stub = string_stub(); | 1263 stub = string_stub(); |
1232 } else if (object->IsJSObject()) { | 1264 } else if (object->IsJSObject()) { |
1233 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1265 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1234 if (receiver->HasExternalArrayElements()) { | 1266 if (receiver->HasExternalArrayElements()) { |
1235 MaybeObject* probe = | 1267 MaybeObject* probe = |
1236 StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, | 1268 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( |
1237 false, | 1269 *receiver, false, kNonStrictMode); |
1238 kNonStrictMode); | |
1239 stub = probe->IsFailure() ? | 1270 stub = probe->IsFailure() ? |
1240 NULL : Code::cast(probe->ToObjectUnchecked()); | 1271 NULL : Code::cast(probe->ToObjectUnchecked()); |
1241 } else if (receiver->HasIndexedInterceptor()) { | 1272 } else if (receiver->HasIndexedInterceptor()) { |
1242 stub = indexed_interceptor_stub(); | 1273 stub = indexed_interceptor_stub(); |
1243 } else if (key->IsSmi() && | 1274 } else if (key->IsSmi() && |
1244 receiver->map()->has_fast_elements()) { | 1275 receiver->map()->has_fast_elements()) { |
1245 MaybeObject* probe = | 1276 MaybeObject* probe = |
1246 StubCache::ComputeKeyedLoadSpecialized(*receiver); | 1277 isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver); |
1247 stub = probe->IsFailure() ? | 1278 stub = probe->IsFailure() ? |
1248 NULL : Code::cast(probe->ToObjectUnchecked()); | 1279 NULL : Code::cast(probe->ToObjectUnchecked()); |
1249 } | 1280 } |
1250 } | 1281 } |
1251 } | 1282 } |
1252 if (stub != NULL) set_target(stub); | 1283 if (stub != NULL) set_target(stub); |
1253 | 1284 |
1254 #ifdef DEBUG | 1285 #ifdef DEBUG |
1255 TraceIC("KeyedLoadIC", key, state, target()); | 1286 TraceIC("KeyedLoadIC", key, state, target()); |
1256 #endif // DEBUG | 1287 #endif // DEBUG |
1257 | 1288 |
1258 // For JSObjects with fast elements that are not value wrappers | 1289 // For JSObjects with fast elements that are not value wrappers |
1259 // and that do not have indexed interceptors, we initialize the | 1290 // and that do not have indexed interceptors, we initialize the |
1260 // inlined fast case (if present) by patching the inlined map | 1291 // inlined fast case (if present) by patching the inlined map |
1261 // check. | 1292 // check. |
1262 if (object->IsJSObject() && | 1293 if (object->IsJSObject() && |
1263 !object->IsJSValue() && | 1294 !object->IsJSValue() && |
1264 !JSObject::cast(*object)->HasIndexedInterceptor() && | 1295 !JSObject::cast(*object)->HasIndexedInterceptor() && |
1265 JSObject::cast(*object)->HasFastElements()) { | 1296 JSObject::cast(*object)->HasFastElements()) { |
1266 Map* map = JSObject::cast(*object)->map(); | 1297 Map* map = JSObject::cast(*object)->map(); |
1267 PatchInlinedLoad(address(), map); | 1298 PatchInlinedLoad(address(), map); |
1268 } | 1299 } |
1269 } | 1300 } |
1270 | 1301 |
1271 // Get the property. | 1302 // Get the property. |
1272 return Runtime::GetObjectProperty(object, key); | 1303 return Runtime::GetObjectProperty(isolate(), object, key); |
1273 } | 1304 } |
1274 | 1305 |
1275 | 1306 |
1276 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 1307 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, |
1277 Handle<Object> object, Handle<String> name) { | 1308 Handle<Object> object, Handle<String> name) { |
1278 // Bail out if we didn't find a result. | 1309 // Bail out if we didn't find a result. |
1279 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 1310 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
1280 | 1311 |
1281 if (!object->IsJSObject()) return; | 1312 if (!object->IsJSObject()) return; |
1282 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1313 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1283 | 1314 |
1284 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; | 1315 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; |
1285 | 1316 |
1286 // Compute the code stub for this load. | 1317 // Compute the code stub for this load. |
1287 MaybeObject* maybe_code = NULL; | 1318 MaybeObject* maybe_code = NULL; |
1288 Object* code; | 1319 Object* code; |
1289 | 1320 |
1290 if (state == UNINITIALIZED) { | 1321 if (state == UNINITIALIZED) { |
1291 // This is the first time we execute this inline cache. | 1322 // This is the first time we execute this inline cache. |
1292 // Set the target to the pre monomorphic stub to delay | 1323 // Set the target to the pre monomorphic stub to delay |
1293 // setting the monomorphic state. | 1324 // setting the monomorphic state. |
1294 maybe_code = pre_monomorphic_stub(); | 1325 maybe_code = pre_monomorphic_stub(); |
1295 } else { | 1326 } else { |
1296 // Compute a monomorphic stub. | 1327 // Compute a monomorphic stub. |
1297 switch (lookup->type()) { | 1328 switch (lookup->type()) { |
1298 case FIELD: { | 1329 case FIELD: { |
1299 maybe_code = StubCache::ComputeKeyedLoadField(*name, *receiver, | 1330 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField( |
1300 lookup->holder(), | 1331 *name, *receiver, lookup->holder(), lookup->GetFieldIndex()); |
1301 lookup->GetFieldIndex()); | |
1302 break; | 1332 break; |
1303 } | 1333 } |
1304 case CONSTANT_FUNCTION: { | 1334 case CONSTANT_FUNCTION: { |
1305 Object* constant = lookup->GetConstantFunction(); | 1335 Object* constant = lookup->GetConstantFunction(); |
1306 maybe_code = StubCache::ComputeKeyedLoadConstant(*name, | 1336 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant( |
1307 *receiver, | 1337 *name, *receiver, lookup->holder(), constant); |
1308 lookup->holder(), | |
1309 constant); | |
1310 break; | 1338 break; |
1311 } | 1339 } |
1312 case CALLBACKS: { | 1340 case CALLBACKS: { |
1313 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1341 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; |
1314 AccessorInfo* callback = | 1342 AccessorInfo* callback = |
1315 AccessorInfo::cast(lookup->GetCallbackObject()); | 1343 AccessorInfo::cast(lookup->GetCallbackObject()); |
1316 if (v8::ToCData<Address>(callback->getter()) == 0) return; | 1344 if (v8::ToCData<Address>(callback->getter()) == 0) return; |
1317 maybe_code = StubCache::ComputeKeyedLoadCallback(*name, | 1345 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback( |
1318 *receiver, | 1346 *name, *receiver, lookup->holder(), callback); |
1319 lookup->holder(), | |
1320 callback); | |
1321 break; | 1347 break; |
1322 } | 1348 } |
1323 case INTERCEPTOR: { | 1349 case INTERCEPTOR: { |
1324 ASSERT(HasInterceptorGetter(lookup->holder())); | 1350 ASSERT(HasInterceptorGetter(lookup->holder())); |
1325 maybe_code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, | 1351 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor( |
1326 lookup->holder()); | 1352 *name, *receiver, lookup->holder()); |
1327 break; | 1353 break; |
1328 } | 1354 } |
1329 default: { | 1355 default: { |
1330 // Always rewrite to the generic case so that we do not | 1356 // Always rewrite to the generic case so that we do not |
1331 // repeatedly try to rewrite. | 1357 // repeatedly try to rewrite. |
1332 maybe_code = generic_stub(); | 1358 maybe_code = generic_stub(); |
1333 break; | 1359 break; |
1334 } | 1360 } |
1335 } | 1361 } |
1336 } | 1362 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 Handle<Object> value) { | 1418 Handle<Object> value) { |
1393 // If the object is undefined or null it's illegal to try to set any | 1419 // If the object is undefined or null it's illegal to try to set any |
1394 // properties on it; throw a TypeError in that case. | 1420 // properties on it; throw a TypeError in that case. |
1395 if (object->IsUndefined() || object->IsNull()) { | 1421 if (object->IsUndefined() || object->IsNull()) { |
1396 return TypeError("non_object_property_store", object, name); | 1422 return TypeError("non_object_property_store", object, name); |
1397 } | 1423 } |
1398 | 1424 |
1399 if (!object->IsJSObject()) { | 1425 if (!object->IsJSObject()) { |
1400 // The length property of string values is read-only. Throw in strict mode. | 1426 // The length property of string values is read-only. Throw in strict mode. |
1401 if (strict_mode == kStrictMode && object->IsString() && | 1427 if (strict_mode == kStrictMode && object->IsString() && |
1402 name->Equals(Heap::length_symbol())) { | 1428 name->Equals(isolate()->heap()->length_symbol())) { |
1403 return TypeError("strict_read_only_property", object, name); | 1429 return TypeError("strict_read_only_property", object, name); |
1404 } | 1430 } |
1405 // Ignore stores where the receiver is not a JSObject. | 1431 // Ignore stores where the receiver is not a JSObject. |
1406 return *value; | 1432 return *value; |
1407 } | 1433 } |
1408 | 1434 |
1409 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1435 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1410 | 1436 |
1411 // Check if the given name is an array index. | 1437 // Check if the given name is an array index. |
1412 uint32_t index; | 1438 uint32_t index; |
1413 if (name->AsArrayIndex(&index)) { | 1439 if (name->AsArrayIndex(&index)) { |
1414 HandleScope scope; | 1440 HandleScope scope(isolate()); |
1415 Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 1441 Handle<Object> result = SetElement(receiver, index, value, strict_mode); |
1416 if (result.is_null()) return Failure::Exception(); | 1442 if (result.is_null()) return Failure::Exception(); |
1417 return *value; | 1443 return *value; |
1418 } | 1444 } |
1419 | 1445 |
1420 // Use specialized code for setting the length of arrays. | 1446 // Use specialized code for setting the length of arrays. |
1421 if (receiver->IsJSArray() | 1447 if (receiver->IsJSArray() |
1422 && name->Equals(Heap::length_symbol()) | 1448 && name->Equals(isolate()->heap()->length_symbol()) |
1423 && receiver->AllowsSetElementsLength()) { | 1449 && receiver->AllowsSetElementsLength()) { |
1424 #ifdef DEBUG | 1450 #ifdef DEBUG |
1425 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); | 1451 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); |
1426 #endif | 1452 #endif |
1427 Builtins::Name target = (strict_mode == kStrictMode) | 1453 Builtins::Name target = (strict_mode == kStrictMode) |
1428 ? Builtins::StoreIC_ArrayLength_Strict | 1454 ? Builtins::StoreIC_ArrayLength_Strict |
1429 : Builtins::StoreIC_ArrayLength; | 1455 : Builtins::StoreIC_ArrayLength; |
1430 set_target(Builtins::builtin(target)); | 1456 set_target(isolate()->builtins()->builtin(target)); |
1431 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1457 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
1432 } | 1458 } |
1433 | 1459 |
1434 // Lookup the property locally in the receiver. | 1460 // Lookup the property locally in the receiver. |
1435 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 1461 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
1436 LookupResult lookup; | 1462 LookupResult lookup; |
1437 | 1463 |
1438 if (LookupForWrite(*receiver, *name, &lookup)) { | 1464 if (LookupForWrite(*receiver, *name, &lookup)) { |
1439 bool can_be_inlined = | 1465 bool can_be_inlined = |
1440 state == UNINITIALIZED && | 1466 state == UNINITIALIZED && |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1536 // current state. | 1562 // current state. |
1537 PropertyType type = lookup->type(); | 1563 PropertyType type = lookup->type(); |
1538 | 1564 |
1539 // Compute the code stub for this store; used for rewriting to | 1565 // Compute the code stub for this store; used for rewriting to |
1540 // monomorphic state and making sure that the code stub is in the | 1566 // monomorphic state and making sure that the code stub is in the |
1541 // stub cache. | 1567 // stub cache. |
1542 MaybeObject* maybe_code = NULL; | 1568 MaybeObject* maybe_code = NULL; |
1543 Object* code = NULL; | 1569 Object* code = NULL; |
1544 switch (type) { | 1570 switch (type) { |
1545 case FIELD: { | 1571 case FIELD: { |
1546 maybe_code = StubCache::ComputeStoreField( | 1572 maybe_code = isolate()->stub_cache()->ComputeStoreField( |
1547 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); | 1573 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); |
1548 break; | 1574 break; |
1549 } | 1575 } |
1550 case MAP_TRANSITION: { | 1576 case MAP_TRANSITION: { |
1551 if (lookup->GetAttributes() != NONE) return; | 1577 if (lookup->GetAttributes() != NONE) return; |
1552 HandleScope scope; | 1578 HandleScope scope(isolate()); |
1553 ASSERT(type == MAP_TRANSITION); | 1579 ASSERT(type == MAP_TRANSITION); |
1554 Handle<Map> transition(lookup->GetTransitionMap()); | 1580 Handle<Map> transition(lookup->GetTransitionMap()); |
1555 int index = transition->PropertyIndexFor(*name); | 1581 int index = transition->PropertyIndexFor(*name); |
1556 maybe_code = StubCache::ComputeStoreField( | 1582 maybe_code = isolate()->stub_cache()->ComputeStoreField( |
1557 *name, *receiver, index, *transition, strict_mode); | 1583 *name, *receiver, index, *transition, strict_mode); |
1558 break; | 1584 break; |
1559 } | 1585 } |
1560 case NORMAL: { | 1586 case NORMAL: { |
1561 if (receiver->IsGlobalObject()) { | 1587 if (receiver->IsGlobalObject()) { |
1562 // The stub generated for the global object picks the value directly | 1588 // The stub generated for the global object picks the value directly |
1563 // from the property cell. So the property must be directly on the | 1589 // from the property cell. So the property must be directly on the |
1564 // global object. | 1590 // global object. |
1565 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1591 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
1566 JSGlobalPropertyCell* cell = | 1592 JSGlobalPropertyCell* cell = |
1567 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 1593 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); |
1568 maybe_code = StubCache::ComputeStoreGlobal( | 1594 maybe_code = isolate()->stub_cache()->ComputeStoreGlobal( |
1569 *name, *global, cell, strict_mode); | 1595 *name, *global, cell, strict_mode); |
1570 } else { | 1596 } else { |
1571 if (lookup->holder() != *receiver) return; | 1597 if (lookup->holder() != *receiver) return; |
1572 maybe_code = StubCache::ComputeStoreNormal(strict_mode); | 1598 maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode); |
1573 } | 1599 } |
1574 break; | 1600 break; |
1575 } | 1601 } |
1576 case CALLBACKS: { | 1602 case CALLBACKS: { |
1577 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1603 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; |
1578 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1604 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
1579 if (v8::ToCData<Address>(callback->setter()) == 0) return; | 1605 if (v8::ToCData<Address>(callback->setter()) == 0) return; |
1580 maybe_code = StubCache::ComputeStoreCallback( | 1606 maybe_code = isolate()->stub_cache()->ComputeStoreCallback( |
1581 *name, *receiver, callback, strict_mode); | 1607 *name, *receiver, callback, strict_mode); |
1582 break; | 1608 break; |
1583 } | 1609 } |
1584 case INTERCEPTOR: { | 1610 case INTERCEPTOR: { |
1585 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1611 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); |
1586 maybe_code = StubCache::ComputeStoreInterceptor( | 1612 maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor( |
1587 *name, *receiver, strict_mode); | 1613 *name, *receiver, strict_mode); |
1588 break; | 1614 break; |
1589 } | 1615 } |
1590 default: | 1616 default: |
1591 return; | 1617 return; |
1592 } | 1618 } |
1593 | 1619 |
1594 // If we're unable to compute the stub (not enough memory left), we | 1620 // If we're unable to compute the stub (not enough memory left), we |
1595 // simply avoid updating the caches. | 1621 // simply avoid updating the caches. |
1596 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 1622 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; |
1597 | 1623 |
1598 // Patch the call site depending on the state of the cache. | 1624 // Patch the call site depending on the state of the cache. |
1599 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 1625 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
1600 set_target(Code::cast(code)); | 1626 set_target(Code::cast(code)); |
1601 } else if (state == MONOMORPHIC) { | 1627 } else if (state == MONOMORPHIC) { |
1602 // Only move to megamorphic if the target changes. | 1628 // Only move to megamorphic if the target changes. |
1603 if (target() != Code::cast(code)) { | 1629 if (target() != Code::cast(code)) { |
1604 set_target((strict_mode == kStrictMode) | 1630 set_target((strict_mode == kStrictMode) |
1605 ? megamorphic_stub_strict() | 1631 ? megamorphic_stub_strict() |
1606 : megamorphic_stub()); | 1632 : megamorphic_stub()); |
1607 } | 1633 } |
1608 } else if (state == MEGAMORPHIC) { | 1634 } else if (state == MEGAMORPHIC) { |
1609 // Update the stub cache. | 1635 // Update the stub cache. |
1610 StubCache::Set(*name, receiver->map(), Code::cast(code)); | 1636 isolate()->stub_cache()->Set(*name, |
| 1637 receiver->map(), |
| 1638 Code::cast(code)); |
1611 } | 1639 } |
1612 | 1640 |
1613 #ifdef DEBUG | 1641 #ifdef DEBUG |
1614 TraceIC("StoreIC", name, state, target()); | 1642 TraceIC("StoreIC", name, state, target()); |
1615 #endif | 1643 #endif |
1616 } | 1644 } |
1617 | 1645 |
1618 | 1646 |
1619 MaybeObject* KeyedStoreIC::Store(State state, | 1647 MaybeObject* KeyedStoreIC::Store(State state, |
1620 StrictModeFlag strict_mode, | 1648 StrictModeFlag strict_mode, |
1621 Handle<Object> object, | 1649 Handle<Object> object, |
1622 Handle<Object> key, | 1650 Handle<Object> key, |
1623 Handle<Object> value) { | 1651 Handle<Object> value) { |
1624 if (key->IsSymbol()) { | 1652 if (key->IsSymbol()) { |
1625 Handle<String> name = Handle<String>::cast(key); | 1653 Handle<String> name = Handle<String>::cast(key); |
1626 | 1654 |
1627 // If the object is undefined or null it's illegal to try to set any | 1655 // If the object is undefined or null it's illegal to try to set any |
1628 // properties on it; throw a TypeError in that case. | 1656 // properties on it; throw a TypeError in that case. |
1629 if (object->IsUndefined() || object->IsNull()) { | 1657 if (object->IsUndefined() || object->IsNull()) { |
1630 return TypeError("non_object_property_store", object, name); | 1658 return TypeError("non_object_property_store", object, name); |
1631 } | 1659 } |
1632 | 1660 |
1633 // Ignore stores where the receiver is not a JSObject. | 1661 // Ignore stores where the receiver is not a JSObject. |
1634 if (!object->IsJSObject()) return *value; | 1662 if (!object->IsJSObject()) return *value; |
1635 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1663 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1636 | 1664 |
1637 // Check if the given name is an array index. | 1665 // Check if the given name is an array index. |
1638 uint32_t index; | 1666 uint32_t index; |
1639 if (name->AsArrayIndex(&index)) { | 1667 if (name->AsArrayIndex(&index)) { |
1640 HandleScope scope; | 1668 HandleScope scope(isolate()); |
1641 Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 1669 Handle<Object> result = SetElement(receiver, index, value, strict_mode); |
1642 if (result.is_null()) return Failure::Exception(); | 1670 if (result.is_null()) return Failure::Exception(); |
1643 return *value; | 1671 return *value; |
1644 } | 1672 } |
1645 | 1673 |
1646 // Lookup the property locally in the receiver. | 1674 // Lookup the property locally in the receiver. |
1647 LookupResult lookup; | 1675 LookupResult lookup; |
1648 receiver->LocalLookup(*name, &lookup); | 1676 receiver->LocalLookup(*name, &lookup); |
1649 | 1677 |
1650 // Update inline cache and stub cache. | 1678 // Update inline cache and stub cache. |
(...skipping 11 matching lines...) Expand all Loading... |
1662 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1690 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
1663 | 1691 |
1664 if (use_ic) { | 1692 if (use_ic) { |
1665 Code* stub = | 1693 Code* stub = |
1666 (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub(); | 1694 (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub(); |
1667 if (state == UNINITIALIZED) { | 1695 if (state == UNINITIALIZED) { |
1668 if (object->IsJSObject()) { | 1696 if (object->IsJSObject()) { |
1669 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1697 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1670 if (receiver->HasExternalArrayElements()) { | 1698 if (receiver->HasExternalArrayElements()) { |
1671 MaybeObject* probe = | 1699 MaybeObject* probe = |
1672 StubCache::ComputeKeyedLoadOrStoreExternalArray( | 1700 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( |
1673 *receiver, true, strict_mode); | 1701 *receiver, true, strict_mode); |
1674 stub = probe->IsFailure() ? | 1702 stub = probe->IsFailure() ? |
1675 NULL : Code::cast(probe->ToObjectUnchecked()); | 1703 NULL : Code::cast(probe->ToObjectUnchecked()); |
1676 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { | 1704 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { |
1677 MaybeObject* probe = | 1705 MaybeObject* probe = |
1678 StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode); | 1706 isolate()->stub_cache()->ComputeKeyedStoreSpecialized( |
| 1707 *receiver, strict_mode); |
1679 stub = probe->IsFailure() ? | 1708 stub = probe->IsFailure() ? |
1680 NULL : Code::cast(probe->ToObjectUnchecked()); | 1709 NULL : Code::cast(probe->ToObjectUnchecked()); |
1681 } | 1710 } |
1682 } | 1711 } |
1683 } | 1712 } |
1684 if (stub != NULL) set_target(stub); | 1713 if (stub != NULL) set_target(stub); |
1685 } | 1714 } |
1686 | 1715 |
1687 // Set the property. | 1716 // Set the property. |
1688 return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode); | 1717 return Runtime::SetObjectProperty( |
| 1718 isolate(), object , key, value, NONE, strict_mode); |
1689 } | 1719 } |
1690 | 1720 |
1691 | 1721 |
1692 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1722 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
1693 State state, | 1723 State state, |
1694 StrictModeFlag strict_mode, | 1724 StrictModeFlag strict_mode, |
1695 Handle<JSObject> receiver, | 1725 Handle<JSObject> receiver, |
1696 Handle<String> name, | 1726 Handle<String> name, |
1697 Handle<Object> value) { | 1727 Handle<Object> value) { |
1698 // Skip JSGlobalProxy. | 1728 // Skip JSGlobalProxy. |
(...skipping 12 matching lines...) Expand all Loading... |
1711 PropertyType type = lookup->type(); | 1741 PropertyType type = lookup->type(); |
1712 | 1742 |
1713 // Compute the code stub for this store; used for rewriting to | 1743 // Compute the code stub for this store; used for rewriting to |
1714 // monomorphic state and making sure that the code stub is in the | 1744 // monomorphic state and making sure that the code stub is in the |
1715 // stub cache. | 1745 // stub cache. |
1716 MaybeObject* maybe_code = NULL; | 1746 MaybeObject* maybe_code = NULL; |
1717 Object* code = NULL; | 1747 Object* code = NULL; |
1718 | 1748 |
1719 switch (type) { | 1749 switch (type) { |
1720 case FIELD: { | 1750 case FIELD: { |
1721 maybe_code = StubCache::ComputeKeyedStoreField( | 1751 maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( |
1722 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); | 1752 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); |
1723 break; | 1753 break; |
1724 } | 1754 } |
1725 case MAP_TRANSITION: { | 1755 case MAP_TRANSITION: { |
1726 if (lookup->GetAttributes() == NONE) { | 1756 if (lookup->GetAttributes() == NONE) { |
1727 HandleScope scope; | 1757 HandleScope scope(isolate()); |
1728 ASSERT(type == MAP_TRANSITION); | 1758 ASSERT(type == MAP_TRANSITION); |
1729 Handle<Map> transition(lookup->GetTransitionMap()); | 1759 Handle<Map> transition(lookup->GetTransitionMap()); |
1730 int index = transition->PropertyIndexFor(*name); | 1760 int index = transition->PropertyIndexFor(*name); |
1731 maybe_code = StubCache::ComputeKeyedStoreField( | 1761 maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( |
1732 *name, *receiver, index, *transition, strict_mode); | 1762 *name, *receiver, index, *transition, strict_mode); |
1733 break; | 1763 break; |
1734 } | 1764 } |
1735 // fall through. | 1765 // fall through. |
1736 } | 1766 } |
1737 default: { | 1767 default: { |
1738 // Always rewrite to the generic case so that we do not | 1768 // Always rewrite to the generic case so that we do not |
1739 // repeatedly try to rewrite. | 1769 // repeatedly try to rewrite. |
1740 maybe_code = (strict_mode == kStrictMode) | 1770 maybe_code = (strict_mode == kStrictMode) |
1741 ? generic_stub_strict() | 1771 ? generic_stub_strict() |
(...skipping 20 matching lines...) Expand all Loading... |
1762 #ifdef DEBUG | 1792 #ifdef DEBUG |
1763 TraceIC("KeyedStoreIC", name, state, target()); | 1793 TraceIC("KeyedStoreIC", name, state, target()); |
1764 #endif | 1794 #endif |
1765 } | 1795 } |
1766 | 1796 |
1767 | 1797 |
1768 // ---------------------------------------------------------------------------- | 1798 // ---------------------------------------------------------------------------- |
1769 // Static IC stub generators. | 1799 // Static IC stub generators. |
1770 // | 1800 // |
1771 | 1801 |
1772 static JSFunction* CompileFunction(JSFunction* function, | 1802 static JSFunction* CompileFunction(Isolate* isolate, |
| 1803 JSFunction* function, |
1773 InLoopFlag in_loop) { | 1804 InLoopFlag in_loop) { |
1774 // Compile now with optimization. | 1805 // Compile now with optimization. |
1775 HandleScope scope; | 1806 HandleScope scope(isolate); |
1776 Handle<JSFunction> function_handle(function); | 1807 Handle<JSFunction> function_handle(function, isolate); |
1777 if (in_loop == IN_LOOP) { | 1808 if (in_loop == IN_LOOP) { |
1778 CompileLazyInLoop(function_handle, CLEAR_EXCEPTION); | 1809 CompileLazyInLoop(function_handle, CLEAR_EXCEPTION); |
1779 } else { | 1810 } else { |
1780 CompileLazy(function_handle, CLEAR_EXCEPTION); | 1811 CompileLazy(function_handle, CLEAR_EXCEPTION); |
1781 } | 1812 } |
1782 return *function_handle; | 1813 return *function_handle; |
1783 } | 1814 } |
1784 | 1815 |
1785 | 1816 |
1786 // Used from ic-<arch>.cc. | 1817 // Used from ic-<arch>.cc. |
1787 MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) { | 1818 MUST_USE_RESULT MaybeObject* CallIC_Miss(RUNTIME_CALLING_CONVENTION) { |
| 1819 RUNTIME_GET_ISOLATE; |
1788 NoHandleAllocation na; | 1820 NoHandleAllocation na; |
1789 ASSERT(args.length() == 2); | 1821 ASSERT(args.length() == 2); |
1790 CallIC ic; | 1822 CallIC ic(isolate); |
1791 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1823 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1792 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1824 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
1793 MaybeObject* maybe_result = ic.LoadFunction(state, | 1825 MaybeObject* maybe_result = ic.LoadFunction(state, |
1794 extra_ic_state, | 1826 extra_ic_state, |
1795 args.at<Object>(0), | 1827 args.at<Object>(0), |
1796 args.at<String>(1)); | 1828 args.at<String>(1)); |
1797 Object* result; | 1829 Object* result; |
1798 if (!maybe_result->ToObject(&result)) return maybe_result; | 1830 if (!maybe_result->ToObject(&result)) return maybe_result; |
1799 | 1831 |
1800 // The first time the inline cache is updated may be the first time the | 1832 // The first time the inline cache is updated may be the first time the |
1801 // function it references gets called. If the function was lazily compiled | 1833 // function it references gets called. If the function was lazily compiled |
1802 // then the first call will trigger a compilation. We check for this case | 1834 // then the first call will trigger a compilation. We check for this case |
1803 // and we do the compilation immediately, instead of waiting for the stub | 1835 // and we do the compilation immediately, instead of waiting for the stub |
1804 // currently attached to the JSFunction object to trigger compilation. We | 1836 // currently attached to the JSFunction object to trigger compilation. We |
1805 // do this in the case where we know that the inline cache is inside a loop, | 1837 // do this in the case where we know that the inline cache is inside a loop, |
1806 // because then we know that we want to optimize the function. | 1838 // because then we know that we want to optimize the function. |
1807 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1839 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { |
1808 return result; | 1840 return result; |
1809 } | 1841 } |
1810 return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop()); | 1842 return CompileFunction(isolate, |
| 1843 JSFunction::cast(result), |
| 1844 ic.target()->ic_in_loop()); |
1811 } | 1845 } |
1812 | 1846 |
1813 | 1847 |
1814 // Used from ic-<arch>.cc. | 1848 // Used from ic-<arch>.cc. |
1815 MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) { | 1849 MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(RUNTIME_CALLING_CONVENTION) { |
| 1850 RUNTIME_GET_ISOLATE; |
1816 NoHandleAllocation na; | 1851 NoHandleAllocation na; |
1817 ASSERT(args.length() == 2); | 1852 ASSERT(args.length() == 2); |
1818 KeyedCallIC ic; | 1853 KeyedCallIC ic(isolate); |
1819 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1854 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1820 Object* result; | 1855 Object* result; |
1821 { MaybeObject* maybe_result = | 1856 { MaybeObject* maybe_result = |
1822 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 1857 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); |
1823 if (!maybe_result->ToObject(&result)) return maybe_result; | 1858 if (!maybe_result->ToObject(&result)) return maybe_result; |
1824 } | 1859 } |
1825 | 1860 |
1826 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1861 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { |
1827 return result; | 1862 return result; |
1828 } | 1863 } |
1829 return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop()); | 1864 return CompileFunction(isolate, |
| 1865 JSFunction::cast(result), |
| 1866 ic.target()->ic_in_loop()); |
1830 } | 1867 } |
1831 | 1868 |
1832 | 1869 |
1833 // Used from ic-<arch>.cc. | 1870 // Used from ic-<arch>.cc. |
1834 MUST_USE_RESULT MaybeObject* LoadIC_Miss(Arguments args) { | 1871 MUST_USE_RESULT MaybeObject* LoadIC_Miss(RUNTIME_CALLING_CONVENTION) { |
| 1872 RUNTIME_GET_ISOLATE; |
1835 NoHandleAllocation na; | 1873 NoHandleAllocation na; |
1836 ASSERT(args.length() == 2); | 1874 ASSERT(args.length() == 2); |
1837 LoadIC ic; | 1875 LoadIC ic(isolate); |
1838 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1876 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1839 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 1877 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
1840 } | 1878 } |
1841 | 1879 |
1842 | 1880 |
1843 // Used from ic-<arch>.cc | 1881 // Used from ic-<arch>.cc |
1844 MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(Arguments args) { | 1882 MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(RUNTIME_CALLING_CONVENTION) { |
| 1883 RUNTIME_GET_ISOLATE; |
1845 NoHandleAllocation na; | 1884 NoHandleAllocation na; |
1846 ASSERT(args.length() == 2); | 1885 ASSERT(args.length() == 2); |
1847 KeyedLoadIC ic; | 1886 KeyedLoadIC ic(isolate); |
1848 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1887 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1849 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); | 1888 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); |
1850 } | 1889 } |
1851 | 1890 |
1852 | 1891 |
1853 // Used from ic-<arch>.cc. | 1892 // Used from ic-<arch>.cc. |
1854 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) { | 1893 MUST_USE_RESULT MaybeObject* StoreIC_Miss(RUNTIME_CALLING_CONVENTION) { |
| 1894 RUNTIME_GET_ISOLATE; |
1855 NoHandleAllocation na; | 1895 NoHandleAllocation na; |
1856 ASSERT(args.length() == 3); | 1896 ASSERT(args.length() == 3); |
1857 StoreIC ic; | 1897 StoreIC ic(isolate); |
1858 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1898 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1859 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1899 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
1860 return ic.Store(state, | 1900 return ic.Store(state, |
1861 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 1901 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), |
1862 args.at<Object>(0), | 1902 args.at<Object>(0), |
1863 args.at<String>(1), | 1903 args.at<String>(1), |
1864 args.at<Object>(2)); | 1904 args.at<Object>(2)); |
1865 } | 1905 } |
1866 | 1906 |
1867 | 1907 |
1868 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) { | 1908 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(RUNTIME_CALLING_CONVENTION) { |
| 1909 RUNTIME_GET_ISOLATE; |
1869 NoHandleAllocation nha; | 1910 NoHandleAllocation nha; |
1870 | 1911 |
1871 ASSERT(args.length() == 2); | 1912 ASSERT(args.length() == 2); |
1872 JSObject* receiver = JSObject::cast(args[0]); | 1913 JSObject* receiver = JSObject::cast(args[0]); |
1873 Object* len = args[1]; | 1914 Object* len = args[1]; |
1874 | 1915 |
1875 // The generated code should filter out non-Smis before we get here. | 1916 // The generated code should filter out non-Smis before we get here. |
1876 ASSERT(len->IsSmi()); | 1917 ASSERT(len->IsSmi()); |
1877 | 1918 |
1878 Object* result; | 1919 Object* result; |
1879 { MaybeObject* maybe_result = receiver->SetElementsLength(len); | 1920 { MaybeObject* maybe_result = receiver->SetElementsLength(len); |
1880 if (!maybe_result->ToObject(&result)) return maybe_result; | 1921 if (!maybe_result->ToObject(&result)) return maybe_result; |
1881 } | 1922 } |
1882 return len; | 1923 return len; |
1883 } | 1924 } |
1884 | 1925 |
1885 | 1926 |
1886 // Extend storage is called in a store inline cache when | 1927 // Extend storage is called in a store inline cache when |
1887 // it is necessary to extend the properties array of a | 1928 // it is necessary to extend the properties array of a |
1888 // JSObject. | 1929 // JSObject. |
1889 MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) { | 1930 MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage( |
| 1931 RUNTIME_CALLING_CONVENTION) { |
| 1932 RUNTIME_GET_ISOLATE; |
1890 NoHandleAllocation na; | 1933 NoHandleAllocation na; |
1891 ASSERT(args.length() == 3); | 1934 ASSERT(args.length() == 3); |
1892 | 1935 |
1893 // Convert the parameters | 1936 // Convert the parameters |
1894 JSObject* object = JSObject::cast(args[0]); | 1937 JSObject* object = JSObject::cast(args[0]); |
1895 Map* transition = Map::cast(args[1]); | 1938 Map* transition = Map::cast(args[1]); |
1896 Object* value = args[2]; | 1939 Object* value = args[2]; |
1897 | 1940 |
1898 // Check the object has run out out property space. | 1941 // Check the object has run out out property space. |
1899 ASSERT(object->HasFastProperties()); | 1942 ASSERT(object->HasFastProperties()); |
(...skipping 13 matching lines...) Expand all Loading... |
1913 // Set the new property value and do the map transition. | 1956 // Set the new property value and do the map transition. |
1914 object->set_properties(new_storage); | 1957 object->set_properties(new_storage); |
1915 object->set_map(transition); | 1958 object->set_map(transition); |
1916 | 1959 |
1917 // Return the stored value. | 1960 // Return the stored value. |
1918 return value; | 1961 return value; |
1919 } | 1962 } |
1920 | 1963 |
1921 | 1964 |
1922 // Used from ic-<arch>.cc. | 1965 // Used from ic-<arch>.cc. |
1923 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) { | 1966 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(RUNTIME_CALLING_CONVENTION) { |
| 1967 RUNTIME_GET_ISOLATE; |
1924 NoHandleAllocation na; | 1968 NoHandleAllocation na; |
1925 ASSERT(args.length() == 3); | 1969 ASSERT(args.length() == 3); |
1926 KeyedStoreIC ic; | 1970 KeyedStoreIC ic(isolate); |
1927 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1971 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1928 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1972 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
1929 return ic.Store(state, | 1973 return ic.Store(state, |
1930 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 1974 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), |
1931 args.at<Object>(0), | 1975 args.at<Object>(0), |
1932 args.at<Object>(1), | 1976 args.at<Object>(1), |
1933 args.at<Object>(2)); | 1977 args.at<Object>(2)); |
1934 } | 1978 } |
1935 | 1979 |
1936 | 1980 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1986 } | 2030 } |
1987 | 2031 |
1988 return GENERIC; | 2032 return GENERIC; |
1989 } | 2033 } |
1990 | 2034 |
1991 | 2035 |
1992 // defined in code-stubs-<arch>.cc | 2036 // defined in code-stubs-<arch>.cc |
1993 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); | 2037 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); |
1994 | 2038 |
1995 | 2039 |
1996 MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) { | 2040 MUST_USE_RESULT MaybeObject* BinaryOp_Patch(RUNTIME_CALLING_CONVENTION) { |
| 2041 RUNTIME_GET_ISOLATE; |
1997 ASSERT(args.length() == 5); | 2042 ASSERT(args.length() == 5); |
1998 | 2043 |
1999 HandleScope scope; | 2044 HandleScope scope(isolate); |
2000 Handle<Object> left = args.at<Object>(0); | 2045 Handle<Object> left = args.at<Object>(0); |
2001 Handle<Object> right = args.at<Object>(1); | 2046 Handle<Object> right = args.at<Object>(1); |
2002 int key = Smi::cast(args[2])->value(); | 2047 int key = Smi::cast(args[2])->value(); |
2003 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); | 2048 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); |
2004 BinaryOpIC::TypeInfo previous_type = | 2049 BinaryOpIC::TypeInfo previous_type = |
2005 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); | 2050 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); |
2006 | 2051 |
2007 BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(*left, *right); | 2052 BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(*left, *right); |
2008 Handle<Code> code = GetBinaryOpStub(key, type); | 2053 Handle<Code> code = GetBinaryOpStub(key, type); |
2009 if (!code.is_null()) { | 2054 if (!code.is_null()) { |
2010 BinaryOpIC ic; | 2055 BinaryOpIC ic(isolate); |
2011 ic.patch(*code); | 2056 ic.patch(*code); |
2012 if (FLAG_trace_ic) { | 2057 if (FLAG_trace_ic) { |
2013 PrintF("[BinaryOpIC (%s->%s)#%s]\n", | 2058 PrintF("[BinaryOpIC (%s->%s)#%s]\n", |
2014 BinaryOpIC::GetName(previous_type), | 2059 BinaryOpIC::GetName(previous_type), |
2015 BinaryOpIC::GetName(type), | 2060 BinaryOpIC::GetName(type), |
2016 Token::Name(op)); | 2061 Token::Name(op)); |
2017 } | 2062 } |
2018 } | 2063 } |
2019 | 2064 |
2020 Handle<JSBuiltinsObject> builtins = Top::builtins(); | 2065 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( |
| 2066 isolate->thread_local_top()->context_->builtins(), isolate); |
2021 Object* builtin = NULL; // Initialization calms down the compiler. | 2067 Object* builtin = NULL; // Initialization calms down the compiler. |
2022 switch (op) { | 2068 switch (op) { |
2023 case Token::ADD: | 2069 case Token::ADD: |
2024 builtin = builtins->javascript_builtin(Builtins::ADD); | 2070 builtin = builtins->javascript_builtin(Builtins::ADD); |
2025 break; | 2071 break; |
2026 case Token::SUB: | 2072 case Token::SUB: |
2027 builtin = builtins->javascript_builtin(Builtins::SUB); | 2073 builtin = builtins->javascript_builtin(Builtins::SUB); |
2028 break; | 2074 break; |
2029 case Token::MUL: | 2075 case Token::MUL: |
2030 builtin = builtins->javascript_builtin(Builtins::MUL); | 2076 builtin = builtins->javascript_builtin(Builtins::MUL); |
(...skipping 19 matching lines...) Expand all Loading... |
2050 case Token::SAR: | 2096 case Token::SAR: |
2051 builtin = builtins->javascript_builtin(Builtins::SAR); | 2097 builtin = builtins->javascript_builtin(Builtins::SAR); |
2052 break; | 2098 break; |
2053 case Token::SHL: | 2099 case Token::SHL: |
2054 builtin = builtins->javascript_builtin(Builtins::SHL); | 2100 builtin = builtins->javascript_builtin(Builtins::SHL); |
2055 break; | 2101 break; |
2056 default: | 2102 default: |
2057 UNREACHABLE(); | 2103 UNREACHABLE(); |
2058 } | 2104 } |
2059 | 2105 |
2060 Handle<JSFunction> builtin_function(JSFunction::cast(builtin)); | 2106 Handle<JSFunction> builtin_function(JSFunction::cast(builtin), |
| 2107 isolate); |
2061 | 2108 |
2062 bool caught_exception; | 2109 bool caught_exception; |
2063 Object** builtin_args[] = { right.location() }; | 2110 Object** builtin_args[] = { right.location() }; |
2064 Handle<Object> result = Execution::Call(builtin_function, | 2111 Handle<Object> result = Execution::Call(builtin_function, |
2065 left, | 2112 left, |
2066 ARRAY_SIZE(builtin_args), | 2113 ARRAY_SIZE(builtin_args), |
2067 builtin_args, | 2114 builtin_args, |
2068 &caught_exception); | 2115 &caught_exception); |
2069 if (caught_exception) { | 2116 if (caught_exception) { |
2070 return Failure::Exception(); | 2117 return Failure::Exception(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2149 } | 2196 } |
2150 | 2197 |
2151 | 2198 |
2152 // defined in code-stubs-<arch>.cc | 2199 // defined in code-stubs-<arch>.cc |
2153 // Only needed to remove dependency of ic.cc on code-stubs-<arch>.h. | 2200 // Only needed to remove dependency of ic.cc on code-stubs-<arch>.h. |
2154 Handle<Code> GetTypeRecordingBinaryOpStub(int key, | 2201 Handle<Code> GetTypeRecordingBinaryOpStub(int key, |
2155 TRBinaryOpIC::TypeInfo type_info, | 2202 TRBinaryOpIC::TypeInfo type_info, |
2156 TRBinaryOpIC::TypeInfo result_type); | 2203 TRBinaryOpIC::TypeInfo result_type); |
2157 | 2204 |
2158 | 2205 |
2159 MaybeObject* TypeRecordingBinaryOp_Patch(Arguments args) { | 2206 MaybeObject* TypeRecordingBinaryOp_Patch(RUNTIME_CALLING_CONVENTION) { |
| 2207 RUNTIME_GET_ISOLATE; |
2160 ASSERT(args.length() == 5); | 2208 ASSERT(args.length() == 5); |
2161 | 2209 |
2162 HandleScope scope; | 2210 HandleScope scope(isolate); |
2163 Handle<Object> left = args.at<Object>(0); | 2211 Handle<Object> left = args.at<Object>(0); |
2164 Handle<Object> right = args.at<Object>(1); | 2212 Handle<Object> right = args.at<Object>(1); |
2165 int key = Smi::cast(args[2])->value(); | 2213 int key = Smi::cast(args[2])->value(); |
2166 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); | 2214 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); |
2167 TRBinaryOpIC::TypeInfo previous_type = | 2215 TRBinaryOpIC::TypeInfo previous_type = |
2168 static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); | 2216 static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); |
2169 | 2217 |
2170 TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right); | 2218 TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right); |
2171 type = TRBinaryOpIC::JoinTypes(type, previous_type); | 2219 type = TRBinaryOpIC::JoinTypes(type, previous_type); |
2172 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED; | 2220 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED; |
(...skipping 21 matching lines...) Expand all Loading... |
2194 | 2242 |
2195 Handle<Code> code = GetTypeRecordingBinaryOpStub(key, type, result_type); | 2243 Handle<Code> code = GetTypeRecordingBinaryOpStub(key, type, result_type); |
2196 if (!code.is_null()) { | 2244 if (!code.is_null()) { |
2197 if (FLAG_trace_ic) { | 2245 if (FLAG_trace_ic) { |
2198 PrintF("[TypeRecordingBinaryOpIC (%s->(%s->%s))#%s]\n", | 2246 PrintF("[TypeRecordingBinaryOpIC (%s->(%s->%s))#%s]\n", |
2199 TRBinaryOpIC::GetName(previous_type), | 2247 TRBinaryOpIC::GetName(previous_type), |
2200 TRBinaryOpIC::GetName(type), | 2248 TRBinaryOpIC::GetName(type), |
2201 TRBinaryOpIC::GetName(result_type), | 2249 TRBinaryOpIC::GetName(result_type), |
2202 Token::Name(op)); | 2250 Token::Name(op)); |
2203 } | 2251 } |
2204 TRBinaryOpIC ic; | 2252 TRBinaryOpIC ic(isolate); |
2205 ic.patch(*code); | 2253 ic.patch(*code); |
2206 | 2254 |
2207 // Activate inlined smi code. | 2255 // Activate inlined smi code. |
2208 if (previous_type == TRBinaryOpIC::UNINITIALIZED) { | 2256 if (previous_type == TRBinaryOpIC::UNINITIALIZED) { |
2209 PatchInlinedSmiCode(ic.address()); | 2257 PatchInlinedSmiCode(ic.address()); |
2210 } | 2258 } |
2211 } | 2259 } |
2212 | 2260 |
2213 Handle<JSBuiltinsObject> builtins = Top::builtins(); | 2261 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( |
| 2262 isolate->thread_local_top()->context_->builtins(), isolate); |
2214 Object* builtin = NULL; // Initialization calms down the compiler. | 2263 Object* builtin = NULL; // Initialization calms down the compiler. |
2215 switch (op) { | 2264 switch (op) { |
2216 case Token::ADD: | 2265 case Token::ADD: |
2217 builtin = builtins->javascript_builtin(Builtins::ADD); | 2266 builtin = builtins->javascript_builtin(Builtins::ADD); |
2218 break; | 2267 break; |
2219 case Token::SUB: | 2268 case Token::SUB: |
2220 builtin = builtins->javascript_builtin(Builtins::SUB); | 2269 builtin = builtins->javascript_builtin(Builtins::SUB); |
2221 break; | 2270 break; |
2222 case Token::MUL: | 2271 case Token::MUL: |
2223 builtin = builtins->javascript_builtin(Builtins::MUL); | 2272 builtin = builtins->javascript_builtin(Builtins::MUL); |
(...skipping 19 matching lines...) Expand all Loading... |
2243 case Token::SAR: | 2292 case Token::SAR: |
2244 builtin = builtins->javascript_builtin(Builtins::SAR); | 2293 builtin = builtins->javascript_builtin(Builtins::SAR); |
2245 break; | 2294 break; |
2246 case Token::SHL: | 2295 case Token::SHL: |
2247 builtin = builtins->javascript_builtin(Builtins::SHL); | 2296 builtin = builtins->javascript_builtin(Builtins::SHL); |
2248 break; | 2297 break; |
2249 default: | 2298 default: |
2250 UNREACHABLE(); | 2299 UNREACHABLE(); |
2251 } | 2300 } |
2252 | 2301 |
2253 Handle<JSFunction> builtin_function(JSFunction::cast(builtin)); | 2302 Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate); |
2254 | 2303 |
2255 bool caught_exception; | 2304 bool caught_exception; |
2256 Object** builtin_args[] = { right.location() }; | 2305 Object** builtin_args[] = { right.location() }; |
2257 Handle<Object> result = Execution::Call(builtin_function, | 2306 Handle<Object> result = Execution::Call(builtin_function, |
2258 left, | 2307 left, |
2259 ARRAY_SIZE(builtin_args), | 2308 ARRAY_SIZE(builtin_args), |
2260 builtin_args, | 2309 builtin_args, |
2261 &caught_exception); | 2310 &caught_exception); |
2262 if (caught_exception) { | 2311 if (caught_exception) { |
2263 return Failure::Exception(); | 2312 return Failure::Exception(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2303 if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) && | 2352 if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) && |
2304 x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS; | 2353 x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS; |
2305 if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC; | 2354 if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC; |
2306 if (state == UNINITIALIZED && | 2355 if (state == UNINITIALIZED && |
2307 x->IsJSObject() && y->IsJSObject()) return OBJECTS; | 2356 x->IsJSObject() && y->IsJSObject()) return OBJECTS; |
2308 return GENERIC; | 2357 return GENERIC; |
2309 } | 2358 } |
2310 | 2359 |
2311 | 2360 |
2312 // Used from ic_<arch>.cc. | 2361 // Used from ic_<arch>.cc. |
2313 Code* CompareIC_Miss(Arguments args) { | 2362 Code* CompareIC_Miss(RUNTIME_CALLING_CONVENTION) { |
| 2363 RUNTIME_GET_ISOLATE; |
2314 NoHandleAllocation na; | 2364 NoHandleAllocation na; |
2315 ASSERT(args.length() == 3); | 2365 ASSERT(args.length() == 3); |
2316 CompareIC ic(static_cast<Token::Value>(Smi::cast(args[2])->value())); | 2366 CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value())); |
2317 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2367 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
2318 return ic.target(); | 2368 return ic.target(); |
2319 } | 2369 } |
2320 | 2370 |
2321 | 2371 |
2322 static Address IC_utilities[] = { | 2372 static const Address IC_utilities[] = { |
2323 #define ADDR(name) FUNCTION_ADDR(name), | 2373 #define ADDR(name) FUNCTION_ADDR(name), |
2324 IC_UTIL_LIST(ADDR) | 2374 IC_UTIL_LIST(ADDR) |
2325 NULL | 2375 NULL |
2326 #undef ADDR | 2376 #undef ADDR |
2327 }; | 2377 }; |
2328 | 2378 |
2329 | 2379 |
2330 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2380 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2331 return IC_utilities[id]; | 2381 return IC_utilities[id]; |
2332 } | 2382 } |
2333 | 2383 |
2334 | 2384 |
2335 } } // namespace v8::internal | 2385 } } // namespace v8::internal |
OLD | NEW |