| 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 |