| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 miss_label, | 121 miss_label, |
| 122 &done, | 122 &done, |
| 123 properties, | 123 properties, |
| 124 name, | 124 name, |
| 125 r1); | 125 r1); |
| 126 __ bind(&done); | 126 __ bind(&done); |
| 127 __ DecrementCounter(counters->negative_lookups_miss(), 1); | 127 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 128 } | 128 } |
| 129 | 129 |
| 130 | 130 |
| 131 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 132 // handlified. | |
| 133 MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup( | |
| 134 MacroAssembler* masm, | |
| 135 Label* miss_label, | |
| 136 Register receiver, | |
| 137 String* name, | |
| 138 Register r0, | |
| 139 Register r1) { | |
| 140 ASSERT(name->IsSymbol()); | |
| 141 Counters* counters = masm->isolate()->counters(); | |
| 142 __ IncrementCounter(counters->negative_lookups(), 1); | |
| 143 __ IncrementCounter(counters->negative_lookups_miss(), 1); | |
| 144 | |
| 145 __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | |
| 146 | |
| 147 const int kInterceptorOrAccessCheckNeededMask = | |
| 148 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | |
| 149 | |
| 150 // Bail out if the receiver has a named interceptor or requires access checks. | |
| 151 __ testb(FieldOperand(r0, Map::kBitFieldOffset), | |
| 152 Immediate(kInterceptorOrAccessCheckNeededMask)); | |
| 153 __ j(not_zero, miss_label); | |
| 154 | |
| 155 // Check that receiver is a JSObject. | |
| 156 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); | |
| 157 __ j(below, miss_label); | |
| 158 | |
| 159 // Load properties array. | |
| 160 Register properties = r0; | |
| 161 __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | |
| 162 | |
| 163 // Check that the properties array is a dictionary. | |
| 164 __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset), | |
| 165 Heap::kHashTableMapRootIndex); | |
| 166 __ j(not_equal, miss_label); | |
| 167 | |
| 168 Label done; | |
| 169 MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup( | |
| 170 masm, | |
| 171 miss_label, | |
| 172 &done, | |
| 173 properties, | |
| 174 name, | |
| 175 r1); | |
| 176 if (result->IsFailure()) return result; | |
| 177 | |
| 178 __ bind(&done); | |
| 179 __ DecrementCounter(counters->negative_lookups_miss(), 1); | |
| 180 | |
| 181 return result; | |
| 182 } | |
| 183 | |
| 184 | |
| 185 void StubCache::GenerateProbe(MacroAssembler* masm, | 131 void StubCache::GenerateProbe(MacroAssembler* masm, |
| 186 Code::Flags flags, | 132 Code::Flags flags, |
| 187 Register receiver, | 133 Register receiver, |
| 188 Register name, | 134 Register name, |
| 189 Register scratch, | 135 Register scratch, |
| 190 Register extra, | 136 Register extra, |
| 191 Register extra2) { | 137 Register extra2) { |
| 192 Isolate* isolate = masm->isolate(); | 138 Isolate* isolate = masm->isolate(); |
| 193 Label miss; | 139 Label miss; |
| 194 USE(extra); // The register extra is not used on the X64 platform. | 140 USE(extra); // The register extra is not used on the X64 platform. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 __ movq(prototype, Operand(prototype, Context::SlotOffset(index))); | 198 __ movq(prototype, Operand(prototype, Context::SlotOffset(index))); |
| 253 // Load the initial map. The global functions all have initial maps. | 199 // Load the initial map. The global functions all have initial maps. |
| 254 __ movq(prototype, | 200 __ movq(prototype, |
| 255 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | 201 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); |
| 256 // Load the prototype from the initial map. | 202 // Load the prototype from the initial map. |
| 257 __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 203 __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
| 258 } | 204 } |
| 259 | 205 |
| 260 | 206 |
| 261 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 207 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
| 262 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 208 MacroAssembler* masm, |
| 209 int index, |
| 210 Register prototype, |
| 211 Label* miss) { |
| 263 Isolate* isolate = masm->isolate(); | 212 Isolate* isolate = masm->isolate(); |
| 264 // Check we're still in the same context. | 213 // Check we're still in the same context. |
| 265 __ Move(prototype, isolate->global()); | 214 __ Move(prototype, isolate->global()); |
| 266 __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)), | 215 __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)), |
| 267 prototype); | 216 prototype); |
| 268 __ j(not_equal, miss); | 217 __ j(not_equal, miss); |
| 269 // Get the global function with the given index. | 218 // Get the global function with the given index. |
| 270 JSFunction* function = | 219 Handle<JSFunction> function( |
| 271 JSFunction::cast(isolate->global_context()->get(index)); | 220 JSFunction::cast(isolate->global_context()->get(index))); |
| 272 // Load its initial map. The global functions all have initial maps. | 221 // Load its initial map. The global functions all have initial maps. |
| 273 __ Move(prototype, Handle<Map>(function->initial_map())); | 222 __ Move(prototype, Handle<Map>(function->initial_map())); |
| 274 // Load the prototype from the initial map. | 223 // Load the prototype from the initial map. |
| 275 __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 224 __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
| 276 } | 225 } |
| 277 | 226 |
| 278 | 227 |
| 279 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 228 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
| 280 Register receiver, | 229 Register receiver, |
| 281 Register scratch, | 230 Register scratch, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 325 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
| 377 __ movq(dst, FieldOperand(dst, offset)); | 326 __ movq(dst, FieldOperand(dst, offset)); |
| 378 } | 327 } |
| 379 } | 328 } |
| 380 | 329 |
| 381 | 330 |
| 382 static void PushInterceptorArguments(MacroAssembler* masm, | 331 static void PushInterceptorArguments(MacroAssembler* masm, |
| 383 Register receiver, | 332 Register receiver, |
| 384 Register holder, | 333 Register holder, |
| 385 Register name, | 334 Register name, |
| 386 JSObject* holder_obj) { | 335 Handle<JSObject> holder_obj) { |
| 387 __ push(name); | 336 __ push(name); |
| 388 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 337 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 389 ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor)); | 338 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 390 __ Move(kScratchRegister, Handle<Object>(interceptor)); | 339 __ Move(kScratchRegister, interceptor); |
| 391 __ push(kScratchRegister); | 340 __ push(kScratchRegister); |
| 392 __ push(receiver); | 341 __ push(receiver); |
| 393 __ push(holder); | 342 __ push(holder); |
| 394 __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset)); | 343 __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset)); |
| 395 } | 344 } |
| 396 | 345 |
| 397 | 346 |
| 398 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 347 static void CompileCallLoadPropertyWithInterceptor( |
| 399 Register receiver, | 348 MacroAssembler* masm, |
| 400 Register holder, | 349 Register receiver, |
| 401 Register name, | 350 Register holder, |
| 402 JSObject* holder_obj) { | 351 Register name, |
| 352 Handle<JSObject> holder_obj) { |
| 403 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 353 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 404 | 354 |
| 405 ExternalReference ref = | 355 ExternalReference ref = |
| 406 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 356 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
| 407 masm->isolate()); | 357 masm->isolate()); |
| 408 __ Set(rax, 5); | 358 __ Set(rax, 5); |
| 409 __ LoadAddress(rbx, ref); | 359 __ LoadAddress(rbx, ref); |
| 410 | 360 |
| 411 CEntryStub stub(1); | 361 CEntryStub stub(1); |
| 412 __ CallStub(&stub); | 362 __ CallStub(&stub); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal | 396 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal |
| 447 // frame. | 397 // frame. |
| 448 // ----------------------------------- | 398 // ----------------------------------- |
| 449 __ movq(scratch, Operand(rsp, 0)); | 399 __ movq(scratch, Operand(rsp, 0)); |
| 450 __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch); | 400 __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch); |
| 451 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); | 401 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); |
| 452 } | 402 } |
| 453 | 403 |
| 454 | 404 |
| 455 // Generates call to API function. | 405 // Generates call to API function. |
| 456 static MaybeObject* GenerateFastApiCall(MacroAssembler* masm, | 406 static void GenerateFastApiCall(MacroAssembler* masm, |
| 457 const CallOptimization& optimization, | 407 const CallOptimization& optimization, |
| 458 int argc) { | 408 int argc) { |
| 459 // ----------- S t a t e ------------- | 409 // ----------- S t a t e ------------- |
| 460 // -- rsp[0] : return address | 410 // -- rsp[0] : return address |
| 461 // -- rsp[8] : object passing the type check | 411 // -- rsp[8] : object passing the type check |
| 462 // (last fast api call extra argument, | 412 // (last fast api call extra argument, |
| 463 // set by CheckPrototypes) | 413 // set by CheckPrototypes) |
| 464 // -- rsp[16] : api function | 414 // -- rsp[16] : api function |
| 465 // (first fast api call extra argument) | 415 // (first fast api call extra argument) |
| 466 // -- rsp[24] : api call data | 416 // -- rsp[24] : api call data |
| 467 // -- rsp[32] : last argument | 417 // -- rsp[32] : last argument |
| 468 // -- ... | 418 // -- ... |
| 469 // -- rsp[(argc + 3) * 8] : first argument | 419 // -- rsp[(argc + 3) * 8] : first argument |
| 470 // -- rsp[(argc + 4) * 8] : receiver | 420 // -- rsp[(argc + 4) * 8] : receiver |
| 471 // ----------------------------------- | 421 // ----------------------------------- |
| 472 // Get the function and setup the context. | 422 // Get the function and setup the context. |
| 473 JSFunction* function = optimization.constant_function(); | 423 Handle<JSFunction> function = optimization.constant_function(); |
| 474 __ Move(rdi, Handle<JSFunction>(function)); | 424 __ Move(rdi, function); |
| 475 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 425 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 476 | 426 |
| 477 // Pass the additional arguments. | 427 // Pass the additional arguments. |
| 478 __ movq(Operand(rsp, 2 * kPointerSize), rdi); | 428 __ movq(Operand(rsp, 2 * kPointerSize), rdi); |
| 479 Object* call_data = optimization.api_call_info()->data(); | 429 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 480 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | 430 Handle<Object> call_data(api_call_info->data()); |
| 481 if (masm->isolate()->heap()->InNewSpace(call_data)) { | 431 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
| 482 __ Move(rcx, api_call_info_handle); | 432 __ Move(rcx, api_call_info); |
| 483 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); | 433 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); |
| 484 __ movq(Operand(rsp, 3 * kPointerSize), rbx); | 434 __ movq(Operand(rsp, 3 * kPointerSize), rbx); |
| 485 } else { | 435 } else { |
| 486 __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(call_data)); | 436 __ Move(Operand(rsp, 3 * kPointerSize), call_data); |
| 487 } | 437 } |
| 488 | 438 |
| 489 // Prepare arguments. | 439 // Prepare arguments. |
| 490 __ lea(rbx, Operand(rsp, 3 * kPointerSize)); | 440 __ lea(rbx, Operand(rsp, 3 * kPointerSize)); |
| 491 | 441 |
| 492 Object* callback = optimization.api_call_info()->callback(); | |
| 493 Address api_function_address = v8::ToCData<Address>(callback); | |
| 494 ApiFunction fun(api_function_address); | |
| 495 | |
| 496 #ifdef _WIN64 | 442 #ifdef _WIN64 |
| 497 // Win64 uses first register--rcx--for returned value. | 443 // Win64 uses first register--rcx--for returned value. |
| 498 Register arguments_arg = rdx; | 444 Register arguments_arg = rdx; |
| 499 #else | 445 #else |
| 500 Register arguments_arg = rdi; | 446 Register arguments_arg = rdi; |
| 501 #endif | 447 #endif |
| 502 | 448 |
| 503 // Allocate the v8::Arguments structure in the arguments' space since | 449 // Allocate the v8::Arguments structure in the arguments' space since |
| 504 // it's not controlled by GC. | 450 // it's not controlled by GC. |
| 505 const int kApiStackSpace = 4; | 451 const int kApiStackSpace = 4; |
| 506 | 452 |
| 507 __ PrepareCallApiFunction(kApiStackSpace); | 453 __ PrepareCallApiFunction(kApiStackSpace); |
| 508 | 454 |
| 509 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. | 455 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. |
| 510 __ addq(rbx, Immediate(argc * kPointerSize)); | 456 __ addq(rbx, Immediate(argc * kPointerSize)); |
| 511 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. | 457 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. |
| 512 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. | 458 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. |
| 513 // v8::Arguments::is_construct_call_. | 459 // v8::Arguments::is_construct_call_. |
| 514 __ Set(StackSpaceOperand(3), 0); | 460 __ Set(StackSpaceOperand(3), 0); |
| 515 | 461 |
| 516 // v8::InvocationCallback's argument. | 462 // v8::InvocationCallback's argument. |
| 517 __ lea(arguments_arg, StackSpaceOperand(0)); | 463 __ lea(arguments_arg, StackSpaceOperand(0)); |
| 518 // Emitting a stub call may try to allocate (if the code is not | 464 |
| 519 // already generated). Do not allow the assembler to perform a | 465 // Function address is a foreign pointer outside V8's heap. |
| 520 // garbage collection but instead return the allocation failure | 466 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 521 // object. | 467 __ CallApiFunctionAndReturn(function_address, |
| 522 return masm->TryCallApiFunctionAndReturn(&fun, | 468 argc + kFastApiCallArguments + 1); |
| 523 argc + kFastApiCallArguments + 1); | |
| 524 } | 469 } |
| 525 | 470 |
| 526 | 471 |
| 527 class CallInterceptorCompiler BASE_EMBEDDED { | 472 class CallInterceptorCompiler BASE_EMBEDDED { |
| 528 public: | 473 public: |
| 529 CallInterceptorCompiler(StubCompiler* stub_compiler, | 474 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 530 const ParameterCount& arguments, | 475 const ParameterCount& arguments, |
| 531 Register name, | 476 Register name, |
| 532 Code::ExtraICState extra_ic_state) | 477 Code::ExtraICState extra_ic_state) |
| 533 : stub_compiler_(stub_compiler), | 478 : stub_compiler_(stub_compiler), |
| 534 arguments_(arguments), | 479 arguments_(arguments), |
| 535 name_(name), | 480 name_(name), |
| 536 extra_ic_state_(extra_ic_state) {} | 481 extra_ic_state_(extra_ic_state) {} |
| 537 | 482 |
| 538 MaybeObject* Compile(MacroAssembler* masm, | 483 void Compile(MacroAssembler* masm, |
| 539 JSObject* object, | 484 Handle<JSObject> object, |
| 540 JSObject* holder, | 485 Handle<JSObject> holder, |
| 541 String* name, | 486 Handle<String> name, |
| 542 LookupResult* lookup, | 487 LookupResult* lookup, |
| 543 Register receiver, | 488 Register receiver, |
| 544 Register scratch1, | 489 Register scratch1, |
| 545 Register scratch2, | 490 Register scratch2, |
| 546 Register scratch3, | 491 Register scratch3, |
| 547 Label* miss) { | 492 Label* miss) { |
| 548 ASSERT(holder->HasNamedInterceptor()); | 493 ASSERT(holder->HasNamedInterceptor()); |
| 549 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 494 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 550 | 495 |
| 551 // Check that the receiver isn't a smi. | 496 // Check that the receiver isn't a smi. |
| 552 __ JumpIfSmi(receiver, miss); | 497 __ JumpIfSmi(receiver, miss); |
| 553 | 498 |
| 554 CallOptimization optimization(lookup); | 499 CallOptimization optimization(lookup); |
| 555 | |
| 556 if (optimization.is_constant_call()) { | 500 if (optimization.is_constant_call()) { |
| 557 return CompileCacheable(masm, | 501 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, |
| 558 object, | 502 holder, lookup, name, optimization, miss); |
| 559 receiver, | |
| 560 scratch1, | |
| 561 scratch2, | |
| 562 scratch3, | |
| 563 holder, | |
| 564 lookup, | |
| 565 name, | |
| 566 optimization, | |
| 567 miss); | |
| 568 } else { | 503 } else { |
| 569 CompileRegular(masm, | 504 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, |
| 570 object, | 505 name, holder, miss); |
| 571 receiver, | |
| 572 scratch1, | |
| 573 scratch2, | |
| 574 scratch3, | |
| 575 name, | |
| 576 holder, | |
| 577 miss); | |
| 578 return masm->isolate()->heap()->undefined_value(); // Success. | |
| 579 } | 506 } |
| 580 } | 507 } |
| 581 | 508 |
| 582 private: | 509 private: |
| 583 MaybeObject* CompileCacheable(MacroAssembler* masm, | 510 void CompileCacheable(MacroAssembler* masm, |
| 584 JSObject* object, | 511 Handle<JSObject> object, |
| 585 Register receiver, | 512 Register receiver, |
| 586 Register scratch1, | 513 Register scratch1, |
| 587 Register scratch2, | 514 Register scratch2, |
| 588 Register scratch3, | 515 Register scratch3, |
| 589 JSObject* interceptor_holder, | 516 Handle<JSObject> interceptor_holder, |
| 590 LookupResult* lookup, | 517 LookupResult* lookup, |
| 591 String* name, | 518 Handle<String> name, |
| 592 const CallOptimization& optimization, | 519 const CallOptimization& optimization, |
| 593 Label* miss_label) { | 520 Label* miss_label) { |
| 594 ASSERT(optimization.is_constant_call()); | 521 ASSERT(optimization.is_constant_call()); |
| 595 ASSERT(!lookup->holder()->IsGlobalObject()); | 522 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 596 | 523 |
| 597 int depth1 = kInvalidProtoDepth; | 524 int depth1 = kInvalidProtoDepth; |
| 598 int depth2 = kInvalidProtoDepth; | 525 int depth2 = kInvalidProtoDepth; |
| 599 bool can_do_fast_api_call = false; | 526 bool can_do_fast_api_call = false; |
| 600 if (optimization.is_simple_api_call() && | 527 if (optimization.is_simple_api_call() && |
| 601 !lookup->holder()->IsGlobalObject()) { | 528 !lookup->holder()->IsGlobalObject()) { |
| 602 depth1 = | 529 depth1 = optimization.GetPrototypeDepthOfExpectedType( |
| 603 optimization.GetPrototypeDepthOfExpectedType(object, | 530 object, interceptor_holder); |
| 604 interceptor_holder); | |
| 605 if (depth1 == kInvalidProtoDepth) { | 531 if (depth1 == kInvalidProtoDepth) { |
| 606 depth2 = | 532 depth2 = optimization.GetPrototypeDepthOfExpectedType( |
| 607 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, | 533 interceptor_holder, Handle<JSObject>(lookup->holder())); |
| 608 lookup->holder()); | |
| 609 } | 534 } |
| 610 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || | 535 can_do_fast_api_call = |
| 611 (depth2 != kInvalidProtoDepth); | 536 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; |
| 612 } | 537 } |
| 613 | 538 |
| 614 Counters* counters = masm->isolate()->counters(); | 539 Counters* counters = masm->isolate()->counters(); |
| 615 __ IncrementCounter(counters->call_const_interceptor(), 1); | 540 __ IncrementCounter(counters->call_const_interceptor(), 1); |
| 616 | 541 |
| 617 if (can_do_fast_api_call) { | 542 if (can_do_fast_api_call) { |
| 618 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); | 543 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
| 619 ReserveSpaceForFastApiCall(masm, scratch1); | 544 ReserveSpaceForFastApiCall(masm, scratch1); |
| 620 } | 545 } |
| 621 | 546 |
| 622 // Check that the maps from receiver to interceptor's holder | 547 // Check that the maps from receiver to interceptor's holder |
| 623 // haven't changed and thus we can invoke interceptor. | 548 // haven't changed and thus we can invoke interceptor. |
| 624 Label miss_cleanup; | 549 Label miss_cleanup; |
| 625 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 550 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 626 Register holder = | 551 Register holder = |
| 627 stub_compiler_->CheckPrototypes(object, receiver, | 552 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
| 628 interceptor_holder, scratch1, | 553 scratch1, scratch2, scratch3, |
| 629 scratch2, scratch3, name, depth1, miss); | 554 name, depth1, miss); |
| 630 | 555 |
| 631 // Invoke an interceptor and if it provides a value, | 556 // Invoke an interceptor and if it provides a value, |
| 632 // branch to |regular_invoke|. | 557 // branch to |regular_invoke|. |
| 633 Label regular_invoke; | 558 Label regular_invoke; |
| 634 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 559 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
| 635 ®ular_invoke); | 560 ®ular_invoke); |
| 636 | 561 |
| 637 // Interceptor returned nothing for this property. Try to use cached | 562 // Interceptor returned nothing for this property. Try to use cached |
| 638 // constant function. | 563 // constant function. |
| 639 | 564 |
| 640 // Check that the maps from interceptor's holder to constant function's | 565 // Check that the maps from interceptor's holder to constant function's |
| 641 // holder haven't changed and thus we can use cached constant function. | 566 // holder haven't changed and thus we can use cached constant function. |
| 642 if (interceptor_holder != lookup->holder()) { | 567 if (*interceptor_holder != lookup->holder()) { |
| 643 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 568 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
| 644 lookup->holder(), scratch1, | 569 Handle<JSObject>(lookup->holder()), |
| 645 scratch2, scratch3, name, depth2, miss); | 570 scratch1, scratch2, scratch3, |
| 571 name, depth2, miss); |
| 646 } else { | 572 } else { |
| 647 // CheckPrototypes has a side effect of fetching a 'holder' | 573 // CheckPrototypes has a side effect of fetching a 'holder' |
| 648 // for API (object which is instanceof for the signature). It's | 574 // for API (object which is instanceof for the signature). It's |
| 649 // safe to omit it here, as if present, it should be fetched | 575 // safe to omit it here, as if present, it should be fetched |
| 650 // by the previous CheckPrototypes. | 576 // by the previous CheckPrototypes. |
| 651 ASSERT(depth2 == kInvalidProtoDepth); | 577 ASSERT(depth2 == kInvalidProtoDepth); |
| 652 } | 578 } |
| 653 | 579 |
| 654 // Invoke function. | 580 // Invoke function. |
| 655 if (can_do_fast_api_call) { | 581 if (can_do_fast_api_call) { |
| 656 MaybeObject* result = GenerateFastApiCall(masm, | 582 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 657 optimization, | |
| 658 arguments_.immediate()); | |
| 659 if (result->IsFailure()) return result; | |
| 660 } else { | 583 } else { |
| 661 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 584 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 662 ? CALL_AS_FUNCTION | 585 ? CALL_AS_FUNCTION |
| 663 : CALL_AS_METHOD; | 586 : CALL_AS_METHOD; |
| 664 __ InvokeFunction(optimization.constant_function(), arguments_, | 587 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 665 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 588 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 666 } | 589 } |
| 667 | 590 |
| 668 // Deferred code for fast API call case---clean preallocated space. | 591 // Deferred code for fast API call case---clean preallocated space. |
| 669 if (can_do_fast_api_call) { | 592 if (can_do_fast_api_call) { |
| 670 __ bind(&miss_cleanup); | 593 __ bind(&miss_cleanup); |
| 671 FreeSpaceForFastApiCall(masm, scratch1); | 594 FreeSpaceForFastApiCall(masm, scratch1); |
| 672 __ jmp(miss_label); | 595 __ jmp(miss_label); |
| 673 } | 596 } |
| 674 | 597 |
| 675 // Invoke a regular function. | 598 // Invoke a regular function. |
| 676 __ bind(®ular_invoke); | 599 __ bind(®ular_invoke); |
| 677 if (can_do_fast_api_call) { | 600 if (can_do_fast_api_call) { |
| 678 FreeSpaceForFastApiCall(masm, scratch1); | 601 FreeSpaceForFastApiCall(masm, scratch1); |
| 679 } | 602 } |
| 680 | |
| 681 return masm->isolate()->heap()->undefined_value(); // Success. | |
| 682 } | 603 } |
| 683 | 604 |
| 684 void CompileRegular(MacroAssembler* masm, | 605 void CompileRegular(MacroAssembler* masm, |
| 685 JSObject* object, | 606 Handle<JSObject> object, |
| 686 Register receiver, | 607 Register receiver, |
| 687 Register scratch1, | 608 Register scratch1, |
| 688 Register scratch2, | 609 Register scratch2, |
| 689 Register scratch3, | 610 Register scratch3, |
| 690 String* name, | 611 Handle<String> name, |
| 691 JSObject* interceptor_holder, | 612 Handle<JSObject> interceptor_holder, |
| 692 Label* miss_label) { | 613 Label* miss_label) { |
| 693 Register holder = | 614 Register holder = |
| 694 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 615 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
| 695 scratch1, scratch2, scratch3, name, | 616 scratch1, scratch2, scratch3, |
| 696 miss_label); | 617 name, miss_label); |
| 697 | 618 |
| 698 FrameScope scope(masm, StackFrame::INTERNAL); | 619 FrameScope scope(masm, StackFrame::INTERNAL); |
| 699 // Save the name_ register across the call. | 620 // Save the name_ register across the call. |
| 700 __ push(name_); | 621 __ push(name_); |
| 701 | 622 |
| 702 PushInterceptorArguments(masm, | 623 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
| 703 receiver, | |
| 704 holder, | |
| 705 name_, | |
| 706 interceptor_holder); | |
| 707 | 624 |
| 708 __ CallExternalReference( | 625 __ CallExternalReference( |
| 709 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 626 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
| 710 masm->isolate()), | 627 masm->isolate()), |
| 711 5); | 628 5); |
| 712 | 629 |
| 713 // Restore the name_ register. | 630 // Restore the name_ register. |
| 714 __ pop(name_); | 631 __ pop(name_); |
| 715 | 632 |
| 716 // Leave the internal frame. | 633 // Leave the internal frame. |
| 717 } | 634 } |
| 718 | 635 |
| 719 void LoadWithInterceptor(MacroAssembler* masm, | 636 void LoadWithInterceptor(MacroAssembler* masm, |
| 720 Register receiver, | 637 Register receiver, |
| 721 Register holder, | 638 Register holder, |
| 722 JSObject* holder_obj, | 639 Handle<JSObject> holder_obj, |
| 723 Label* interceptor_succeeded) { | 640 Label* interceptor_succeeded) { |
| 724 { | 641 { |
| 725 FrameScope scope(masm, StackFrame::INTERNAL); | 642 FrameScope scope(masm, StackFrame::INTERNAL); |
| 726 __ push(holder); // Save the holder. | 643 __ push(holder); // Save the holder. |
| 727 __ push(name_); // Save the name. | 644 __ push(name_); // Save the name. |
| 728 | 645 |
| 729 CompileCallLoadPropertyWithInterceptor(masm, | 646 CompileCallLoadPropertyWithInterceptor(masm, |
| 730 receiver, | 647 receiver, |
| 731 holder, | 648 holder, |
| 732 name_, | 649 name_, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 751 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 668 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
| 752 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 669 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
| 753 Handle<Code> code = (kind == Code::LOAD_IC) | 670 Handle<Code> code = (kind == Code::LOAD_IC) |
| 754 ? masm->isolate()->builtins()->LoadIC_Miss() | 671 ? masm->isolate()->builtins()->LoadIC_Miss() |
| 755 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); | 672 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); |
| 756 __ Jump(code, RelocInfo::CODE_TARGET); | 673 __ Jump(code, RelocInfo::CODE_TARGET); |
| 757 } | 674 } |
| 758 | 675 |
| 759 | 676 |
| 760 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { | 677 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { |
| 761 Code* code = masm->isolate()->builtins()->builtin( | 678 Handle<Code> code = |
| 762 Builtins::kKeyedLoadIC_MissForceGeneric); | 679 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 763 Handle<Code> ic(code); | 680 __ Jump(code, RelocInfo::CODE_TARGET); |
| 764 __ Jump(ic, RelocInfo::CODE_TARGET); | |
| 765 } | 681 } |
| 766 | 682 |
| 767 | 683 |
| 768 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 684 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 769 // but may be destroyed if store is successful. | 685 // but may be destroyed if store is successful. |
| 770 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 686 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 771 Handle<JSObject> object, | 687 Handle<JSObject> object, |
| 772 int index, | 688 int index, |
| 773 Handle<Map> transition, | 689 Handle<Map> transition, |
| 774 Register receiver_reg, | 690 Register receiver_reg, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 860 Handle<JSGlobalPropertyCell> cell = | 776 Handle<JSGlobalPropertyCell> cell = |
| 861 GlobalObject::EnsurePropertyCell(global, name); | 777 GlobalObject::EnsurePropertyCell(global, name); |
| 862 ASSERT(cell->value()->IsTheHole()); | 778 ASSERT(cell->value()->IsTheHole()); |
| 863 __ Move(scratch, cell); | 779 __ Move(scratch, cell); |
| 864 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 780 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 865 masm->isolate()->factory()->the_hole_value()); | 781 masm->isolate()->factory()->the_hole_value()); |
| 866 __ j(not_equal, miss); | 782 __ j(not_equal, miss); |
| 867 } | 783 } |
| 868 | 784 |
| 869 | 785 |
| 870 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 871 // handlified. | |
| 872 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( | |
| 873 MacroAssembler* masm, | |
| 874 GlobalObject* global, | |
| 875 String* name, | |
| 876 Register scratch, | |
| 877 Label* miss) { | |
| 878 Object* probe; | |
| 879 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | |
| 880 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | |
| 881 } | |
| 882 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | |
| 883 ASSERT(cell->value()->IsTheHole()); | |
| 884 __ Move(scratch, Handle<Object>(cell)); | |
| 885 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | |
| 886 masm->isolate()->factory()->the_hole_value()); | |
| 887 __ j(not_equal, miss); | |
| 888 return cell; | |
| 889 } | |
| 890 | |
| 891 | |
| 892 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 786 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
| 893 // from object to (but not including) holder. | 787 // from object to (but not including) holder. |
| 894 static void GenerateCheckPropertyCells(MacroAssembler* masm, | 788 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 895 Handle<JSObject> object, | 789 Handle<JSObject> object, |
| 896 Handle<JSObject> holder, | 790 Handle<JSObject> holder, |
| 897 Handle<String> name, | 791 Handle<String> name, |
| 898 Register scratch, | 792 Register scratch, |
| 899 Label* miss) { | 793 Label* miss) { |
| 900 Handle<JSObject> current = object; | 794 Handle<JSObject> current = object; |
| 901 while (!current.is_identical_to(holder)) { | 795 while (!current.is_identical_to(holder)) { |
| 902 if (current->IsGlobalObject()) { | 796 if (current->IsGlobalObject()) { |
| 903 GenerateCheckPropertyCell(masm, | 797 GenerateCheckPropertyCell(masm, |
| 904 Handle<GlobalObject>::cast(current), | 798 Handle<GlobalObject>::cast(current), |
| 905 name, | 799 name, |
| 906 scratch, | 800 scratch, |
| 907 miss); | 801 miss); |
| 908 } | 802 } |
| 909 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 803 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 910 } | 804 } |
| 911 } | 805 } |
| 912 | 806 |
| 913 | |
| 914 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 915 // handlified. | |
| 916 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( | |
| 917 MacroAssembler* masm, | |
| 918 JSObject* object, | |
| 919 JSObject* holder, | |
| 920 String* name, | |
| 921 Register scratch, | |
| 922 Label* miss) { | |
| 923 JSObject* current = object; | |
| 924 while (current != holder) { | |
| 925 if (current->IsGlobalObject()) { | |
| 926 // Returns a cell or a failure. | |
| 927 MaybeObject* result = TryGenerateCheckPropertyCell( | |
| 928 masm, | |
| 929 GlobalObject::cast(current), | |
| 930 name, | |
| 931 scratch, | |
| 932 miss); | |
| 933 if (result->IsFailure()) return result; | |
| 934 } | |
| 935 ASSERT(current->IsJSObject()); | |
| 936 current = JSObject::cast(current->GetPrototype()); | |
| 937 } | |
| 938 return NULL; | |
| 939 } | |
| 940 | |
| 941 | |
| 942 #undef __ | 807 #undef __ |
| 943 #define __ ACCESS_MASM((masm())) | 808 #define __ ACCESS_MASM((masm())) |
| 944 | 809 |
| 945 | 810 |
| 946 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 811 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 947 Register object_reg, | 812 Register object_reg, |
| 948 Handle<JSObject> holder, | 813 Handle<JSObject> holder, |
| 949 Register holder_reg, | 814 Register holder_reg, |
| 950 Register scratch1, | 815 Register scratch1, |
| 951 Register scratch2, | 816 Register scratch2, |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 // If we've skipped any global objects, it's not enough to verify that | 913 // If we've skipped any global objects, it's not enough to verify that |
| 1049 // their maps haven't changed. We also need to check that the property | 914 // their maps haven't changed. We also need to check that the property |
| 1050 // cell for the property is still empty. | 915 // cell for the property is still empty. |
| 1051 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 916 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1052 | 917 |
| 1053 // Return the register containing the holder. | 918 // Return the register containing the holder. |
| 1054 return reg; | 919 return reg; |
| 1055 } | 920 } |
| 1056 | 921 |
| 1057 | 922 |
| 1058 Register StubCompiler::CheckPrototypes(JSObject* object, | |
| 1059 Register object_reg, | |
| 1060 JSObject* holder, | |
| 1061 Register holder_reg, | |
| 1062 Register scratch1, | |
| 1063 Register scratch2, | |
| 1064 String* name, | |
| 1065 int save_at_depth, | |
| 1066 Label* miss) { | |
| 1067 // Make sure there's no overlap between holder and object registers. | |
| 1068 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | |
| 1069 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | |
| 1070 && !scratch2.is(scratch1)); | |
| 1071 | |
| 1072 // Keep track of the current object in register reg. On the first | |
| 1073 // iteration, reg is an alias for object_reg, on later iterations, | |
| 1074 // it is an alias for holder_reg. | |
| 1075 Register reg = object_reg; | |
| 1076 int depth = 0; | |
| 1077 | |
| 1078 if (save_at_depth == depth) { | |
| 1079 __ movq(Operand(rsp, kPointerSize), object_reg); | |
| 1080 } | |
| 1081 | |
| 1082 // Check the maps in the prototype chain. | |
| 1083 // Traverse the prototype chain from the object and do map checks. | |
| 1084 JSObject* current = object; | |
| 1085 while (current != holder) { | |
| 1086 depth++; | |
| 1087 | |
| 1088 // Only global objects and objects that do not require access | |
| 1089 // checks are allowed in stubs. | |
| 1090 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | |
| 1091 | |
| 1092 JSObject* prototype = JSObject::cast(current->GetPrototype()); | |
| 1093 if (!current->HasFastProperties() && | |
| 1094 !current->IsJSGlobalObject() && | |
| 1095 !current->IsJSGlobalProxy()) { | |
| 1096 if (!name->IsSymbol()) { | |
| 1097 MaybeObject* lookup_result = heap()->LookupSymbol(name); | |
| 1098 if (lookup_result->IsFailure()) { | |
| 1099 set_failure(Failure::cast(lookup_result)); | |
| 1100 return reg; | |
| 1101 } else { | |
| 1102 name = String::cast(lookup_result->ToObjectUnchecked()); | |
| 1103 } | |
| 1104 } | |
| 1105 ASSERT(current->property_dictionary()->FindEntry(name) == | |
| 1106 StringDictionary::kNotFound); | |
| 1107 | |
| 1108 MaybeObject* negative_lookup = | |
| 1109 TryGenerateDictionaryNegativeLookup(masm(), | |
| 1110 miss, | |
| 1111 reg, | |
| 1112 name, | |
| 1113 scratch1, | |
| 1114 scratch2); | |
| 1115 if (negative_lookup->IsFailure()) { | |
| 1116 set_failure(Failure::cast(negative_lookup)); | |
| 1117 return reg; | |
| 1118 } | |
| 1119 | |
| 1120 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | |
| 1121 reg = holder_reg; // from now the object is in holder_reg | |
| 1122 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | |
| 1123 } else if (heap()->InNewSpace(prototype)) { | |
| 1124 // Get the map of the current object. | |
| 1125 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | |
| 1126 __ Cmp(scratch1, Handle<Map>(current->map())); | |
| 1127 // Branch on the result of the map check. | |
| 1128 __ j(not_equal, miss); | |
| 1129 // Check access rights to the global object. This has to happen | |
| 1130 // after the map check so that we know that the object is | |
| 1131 // actually a global object. | |
| 1132 if (current->IsJSGlobalProxy()) { | |
| 1133 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1134 | |
| 1135 // Restore scratch register to be the map of the object. | |
| 1136 // We load the prototype from the map in the scratch register. | |
| 1137 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | |
| 1138 } | |
| 1139 // The prototype is in new space; we cannot store a reference | |
| 1140 // to it in the code. Load it from the map. | |
| 1141 reg = holder_reg; // from now the object is in holder_reg | |
| 1142 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | |
| 1143 | |
| 1144 } else { | |
| 1145 // Check the map of the current object. | |
| 1146 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), | |
| 1147 Handle<Map>(current->map())); | |
| 1148 // Branch on the result of the map check. | |
| 1149 __ j(not_equal, miss); | |
| 1150 // Check access rights to the global object. This has to happen | |
| 1151 // after the map check so that we know that the object is | |
| 1152 // actually a global object. | |
| 1153 if (current->IsJSGlobalProxy()) { | |
| 1154 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1155 } | |
| 1156 // The prototype is in old space; load it directly. | |
| 1157 reg = holder_reg; // from now the object is in holder_reg | |
| 1158 __ Move(reg, Handle<JSObject>(prototype)); | |
| 1159 } | |
| 1160 | |
| 1161 if (save_at_depth == depth) { | |
| 1162 __ movq(Operand(rsp, kPointerSize), reg); | |
| 1163 } | |
| 1164 | |
| 1165 // Go to the next object in the prototype chain. | |
| 1166 current = prototype; | |
| 1167 } | |
| 1168 | |
| 1169 // Check the holder map. | |
| 1170 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map())); | |
| 1171 __ j(not_equal, miss); | |
| 1172 | |
| 1173 // Log the check depth. | |
| 1174 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | |
| 1175 | |
| 1176 // Perform security check for access to the global object and return | |
| 1177 // the holder register. | |
| 1178 ASSERT(current == holder); | |
| 1179 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | |
| 1180 if (current->IsJSGlobalProxy()) { | |
| 1181 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1182 } | |
| 1183 | |
| 1184 // If we've skipped any global objects, it's not enough to verify | |
| 1185 // that their maps haven't changed. We also need to check that the | |
| 1186 // property cell for the property is still empty. | |
| 1187 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), | |
| 1188 object, | |
| 1189 holder, | |
| 1190 name, | |
| 1191 scratch1, | |
| 1192 miss); | |
| 1193 if (result->IsFailure()) set_failure(Failure::cast(result)); | |
| 1194 | |
| 1195 // Return the register containing the holder. | |
| 1196 return reg; | |
| 1197 } | |
| 1198 | |
| 1199 | |
| 1200 void StubCompiler::GenerateLoadField(Handle<JSObject> object, | 923 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
| 1201 Handle<JSObject> holder, | 924 Handle<JSObject> holder, |
| 1202 Register receiver, | 925 Register receiver, |
| 1203 Register scratch1, | 926 Register scratch1, |
| 1204 Register scratch2, | 927 Register scratch2, |
| 1205 Register scratch3, | 928 Register scratch3, |
| 1206 int index, | 929 int index, |
| 1207 Handle<String> name, | 930 Handle<String> name, |
| 1208 Label* miss) { | 931 Label* miss) { |
| 1209 // Check that the receiver isn't a smi. | 932 // Check that the receiver isn't a smi. |
| 1210 __ JumpIfSmi(receiver, miss); | 933 __ JumpIfSmi(receiver, miss); |
| 1211 | 934 |
| 1212 // Check the prototype chain. | 935 // Check the prototype chain. |
| 1213 Register reg = CheckPrototypes( | 936 Register reg = CheckPrototypes( |
| 1214 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); | 937 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
| 1215 | 938 |
| 1216 // Get the value from the properties. | 939 // Get the value from the properties. |
| 1217 GenerateFastPropertyLoad(masm(), rax, reg, holder, index); | 940 GenerateFastPropertyLoad(masm(), rax, reg, holder, index); |
| 1218 __ ret(0); | 941 __ ret(0); |
| 1219 } | 942 } |
| 1220 | 943 |
| 1221 | 944 |
| 1222 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 945 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, |
| 1223 JSObject* holder, | 946 Handle<JSObject> holder, |
| 1224 Register receiver, | 947 Register receiver, |
| 1225 Register name_reg, | 948 Register name_reg, |
| 1226 Register scratch1, | 949 Register scratch1, |
| 1227 Register scratch2, | 950 Register scratch2, |
| 1228 Register scratch3, | 951 Register scratch3, |
| 1229 AccessorInfo* callback, | 952 Handle<AccessorInfo> callback, |
| 1230 String* name, | 953 Handle<String> name, |
| 1231 Label* miss) { | 954 Label* miss) { |
| 1232 // Check that the receiver isn't a smi. | 955 // Check that the receiver isn't a smi. |
| 1233 __ JumpIfSmi(receiver, miss); | 956 __ JumpIfSmi(receiver, miss); |
| 1234 | 957 |
| 1235 // Check that the maps haven't changed. | 958 // Check that the maps haven't changed. |
| 1236 Register reg = | 959 Register reg = CheckPrototypes(object, receiver, holder, scratch1, |
| 1237 CheckPrototypes(object, receiver, holder, scratch1, | 960 scratch2, scratch3, name, miss); |
| 1238 scratch2, scratch3, name, miss); | |
| 1239 | |
| 1240 Handle<AccessorInfo> callback_handle(callback); | |
| 1241 | 961 |
| 1242 // Insert additional parameters into the stack frame above return address. | 962 // Insert additional parameters into the stack frame above return address. |
| 1243 ASSERT(!scratch2.is(reg)); | 963 ASSERT(!scratch2.is(reg)); |
| 1244 __ pop(scratch2); // Get return address to place it below. | 964 __ pop(scratch2); // Get return address to place it below. |
| 1245 | 965 |
| 1246 __ push(receiver); // receiver | 966 __ push(receiver); // receiver |
| 1247 __ push(reg); // holder | 967 __ push(reg); // holder |
| 1248 if (heap()->InNewSpace(callback_handle->data())) { | 968 if (heap()->InNewSpace(callback->data())) { |
| 1249 __ Move(scratch1, callback_handle); | 969 __ Move(scratch1, callback); |
| 1250 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data | 970 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data |
| 1251 } else { | 971 } else { |
| 1252 __ Push(Handle<Object>(callback_handle->data())); | 972 __ Push(Handle<Object>(callback->data())); |
| 1253 } | 973 } |
| 1254 __ push(name_reg); // name | 974 __ push(name_reg); // name |
| 1255 // Save a pointer to where we pushed the arguments pointer. | 975 // Save a pointer to where we pushed the arguments pointer. |
| 1256 // This will be passed as the const AccessorInfo& to the C++ callback. | 976 // This will be passed as the const AccessorInfo& to the C++ callback. |
| 1257 | 977 |
| 1258 #ifdef _WIN64 | 978 #ifdef _WIN64 |
| 1259 // Win64 uses first register--rcx--for returned value. | 979 // Win64 uses first register--rcx--for returned value. |
| 1260 Register accessor_info_arg = r8; | 980 Register accessor_info_arg = r8; |
| 1261 Register name_arg = rdx; | 981 Register name_arg = rdx; |
| 1262 #else | 982 #else |
| 1263 Register accessor_info_arg = rsi; | 983 Register accessor_info_arg = rsi; |
| 1264 Register name_arg = rdi; | 984 Register name_arg = rdi; |
| 1265 #endif | 985 #endif |
| 1266 | 986 |
| 1267 ASSERT(!name_arg.is(scratch2)); | 987 ASSERT(!name_arg.is(scratch2)); |
| 1268 __ movq(name_arg, rsp); | 988 __ movq(name_arg, rsp); |
| 1269 __ push(scratch2); // Restore return address. | 989 __ push(scratch2); // Restore return address. |
| 1270 | 990 |
| 1271 // Do call through the api. | |
| 1272 Address getter_address = v8::ToCData<Address>(callback->getter()); | |
| 1273 ApiFunction fun(getter_address); | |
| 1274 | |
| 1275 // 3 elements array for v8::Agruments::values_ and handler for name. | 991 // 3 elements array for v8::Agruments::values_ and handler for name. |
| 1276 const int kStackSpace = 4; | 992 const int kStackSpace = 4; |
| 1277 | 993 |
| 1278 // Allocate v8::AccessorInfo in non-GCed stack space. | 994 // Allocate v8::AccessorInfo in non-GCed stack space. |
| 1279 const int kArgStackSpace = 1; | 995 const int kArgStackSpace = 1; |
| 1280 | 996 |
| 1281 __ PrepareCallApiFunction(kArgStackSpace); | 997 __ PrepareCallApiFunction(kArgStackSpace); |
| 1282 __ lea(rax, Operand(name_arg, 3 * kPointerSize)); | 998 __ lea(rax, Operand(name_arg, 3 * kPointerSize)); |
| 1283 | 999 |
| 1284 // v8::AccessorInfo::args_. | 1000 // v8::AccessorInfo::args_. |
| 1285 __ movq(StackSpaceOperand(0), rax); | 1001 __ movq(StackSpaceOperand(0), rax); |
| 1286 | 1002 |
| 1287 // The context register (rsi) has been saved in PrepareCallApiFunction and | 1003 // The context register (rsi) has been saved in PrepareCallApiFunction and |
| 1288 // could be used to pass arguments. | 1004 // could be used to pass arguments. |
| 1289 __ lea(accessor_info_arg, StackSpaceOperand(0)); | 1005 __ lea(accessor_info_arg, StackSpaceOperand(0)); |
| 1290 | 1006 |
| 1291 // Emitting a stub call may try to allocate (if the code is not | 1007 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 1292 // already generated). Do not allow the assembler to perform a | 1008 __ CallApiFunctionAndReturn(getter_address, kStackSpace); |
| 1293 // garbage collection but instead return the allocation failure | |
| 1294 // object. | |
| 1295 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); | |
| 1296 } | 1009 } |
| 1297 | 1010 |
| 1298 | 1011 |
| 1299 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, | 1012 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, |
| 1300 Handle<JSObject> holder, | 1013 Handle<JSObject> holder, |
| 1301 Register receiver, | 1014 Register receiver, |
| 1302 Register scratch1, | 1015 Register scratch1, |
| 1303 Register scratch2, | 1016 Register scratch2, |
| 1304 Register scratch3, | 1017 Register scratch3, |
| 1305 Handle<Object> value, | 1018 Handle<Object> value, |
| 1306 Handle<String> name, | 1019 Handle<String> name, |
| 1307 Label* miss) { | 1020 Label* miss) { |
| 1308 // Check that the receiver isn't a smi. | 1021 // Check that the receiver isn't a smi. |
| 1309 __ JumpIfSmi(receiver, miss); | 1022 __ JumpIfSmi(receiver, miss); |
| 1310 | 1023 |
| 1311 // Check that the maps haven't changed. | 1024 // Check that the maps haven't changed. |
| 1312 CheckPrototypes( | 1025 CheckPrototypes( |
| 1313 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); | 1026 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
| 1314 | 1027 |
| 1315 // Return the constant value. | 1028 // Return the constant value. |
| 1316 __ Move(rax, value); | 1029 __ Move(rax, value); |
| 1317 __ ret(0); | 1030 __ ret(0); |
| 1318 } | 1031 } |
| 1319 | 1032 |
| 1320 | 1033 |
| 1321 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1034 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, |
| 1322 JSObject* interceptor_holder, | 1035 Handle<JSObject> interceptor_holder, |
| 1323 LookupResult* lookup, | 1036 LookupResult* lookup, |
| 1324 Register receiver, | 1037 Register receiver, |
| 1325 Register name_reg, | 1038 Register name_reg, |
| 1326 Register scratch1, | 1039 Register scratch1, |
| 1327 Register scratch2, | 1040 Register scratch2, |
| 1328 Register scratch3, | 1041 Register scratch3, |
| 1329 String* name, | 1042 Handle<String> name, |
| 1330 Label* miss) { | 1043 Label* miss) { |
| 1331 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1044 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1332 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1045 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1333 | 1046 |
| 1334 // Check that the receiver isn't a smi. | 1047 // Check that the receiver isn't a smi. |
| 1335 __ JumpIfSmi(receiver, miss); | 1048 __ JumpIfSmi(receiver, miss); |
| 1336 | 1049 |
| 1337 // So far the most popular follow ups for interceptor loads are FIELD | 1050 // So far the most popular follow ups for interceptor loads are FIELD |
| 1338 // and CALLBACKS, so inline only them, other cases may be added | 1051 // and CALLBACKS, so inline only them, other cases may be added |
| 1339 // later. | 1052 // later. |
| 1340 bool compile_followup_inline = false; | 1053 bool compile_followup_inline = false; |
| 1341 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1054 if (lookup->IsProperty() && lookup->IsCacheable()) { |
| 1342 if (lookup->type() == FIELD) { | 1055 if (lookup->type() == FIELD) { |
| 1343 compile_followup_inline = true; | 1056 compile_followup_inline = true; |
| 1344 } else if (lookup->type() == CALLBACKS && | 1057 } else if (lookup->type() == CALLBACKS && |
| 1345 lookup->GetCallbackObject()->IsAccessorInfo() && | 1058 lookup->GetCallbackObject()->IsAccessorInfo()) { |
| 1346 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { | 1059 compile_followup_inline = |
| 1347 compile_followup_inline = true; | 1060 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; |
| 1348 } | 1061 } |
| 1349 } | 1062 } |
| 1350 | 1063 |
| 1351 if (compile_followup_inline) { | 1064 if (compile_followup_inline) { |
| 1352 // Compile the interceptor call, followed by inline code to load the | 1065 // Compile the interceptor call, followed by inline code to load the |
| 1353 // property from further up the prototype chain if the call fails. | 1066 // property from further up the prototype chain if the call fails. |
| 1354 // Check that the maps haven't changed. | 1067 // Check that the maps haven't changed. |
| 1355 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1068 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
| 1356 scratch1, scratch2, scratch3, | 1069 scratch1, scratch2, scratch3, |
| 1357 name, miss); | 1070 name, miss); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1391 __ pop(holder_reg); | 1104 __ pop(holder_reg); |
| 1392 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1105 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
| 1393 __ pop(receiver); | 1106 __ pop(receiver); |
| 1394 } | 1107 } |
| 1395 | 1108 |
| 1396 // Leave the internal frame. | 1109 // Leave the internal frame. |
| 1397 } | 1110 } |
| 1398 | 1111 |
| 1399 // Check that the maps from interceptor's holder to lookup's holder | 1112 // Check that the maps from interceptor's holder to lookup's holder |
| 1400 // haven't changed. And load lookup's holder into |holder| register. | 1113 // haven't changed. And load lookup's holder into |holder| register. |
| 1401 if (interceptor_holder != lookup->holder()) { | 1114 if (*interceptor_holder != lookup->holder()) { |
| 1402 holder_reg = CheckPrototypes(interceptor_holder, | 1115 holder_reg = CheckPrototypes(interceptor_holder, |
| 1403 holder_reg, | 1116 holder_reg, |
| 1404 lookup->holder(), | 1117 Handle<JSObject>(lookup->holder()), |
| 1405 scratch1, | 1118 scratch1, |
| 1406 scratch2, | 1119 scratch2, |
| 1407 scratch3, | 1120 scratch3, |
| 1408 name, | 1121 name, |
| 1409 miss); | 1122 miss); |
| 1410 } | 1123 } |
| 1411 | 1124 |
| 1412 if (lookup->type() == FIELD) { | 1125 if (lookup->type() == FIELD) { |
| 1413 // We found FIELD property in prototype chain of interceptor's holder. | 1126 // We found FIELD property in prototype chain of interceptor's holder. |
| 1414 // Retrieve a field from field's holder. | 1127 // Retrieve a field from field's holder. |
| 1415 GenerateFastPropertyLoad(masm(), rax, holder_reg, | 1128 GenerateFastPropertyLoad(masm(), rax, holder_reg, |
| 1416 Handle<JSObject>(lookup->holder()), | 1129 Handle<JSObject>(lookup->holder()), |
| 1417 lookup->GetFieldIndex()); | 1130 lookup->GetFieldIndex()); |
| 1418 __ ret(0); | 1131 __ ret(0); |
| 1419 } else { | 1132 } else { |
| 1420 // We found CALLBACKS property in prototype chain of interceptor's | 1133 // We found CALLBACKS property in prototype chain of interceptor's |
| 1421 // holder. | 1134 // holder. |
| 1422 ASSERT(lookup->type() == CALLBACKS); | 1135 ASSERT(lookup->type() == CALLBACKS); |
| 1423 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1136 Handle<AccessorInfo> callback( |
| 1424 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1137 AccessorInfo::cast(lookup->GetCallbackObject())); |
| 1425 ASSERT(callback != NULL); | |
| 1426 ASSERT(callback->getter() != NULL); | 1138 ASSERT(callback->getter() != NULL); |
| 1427 | 1139 |
| 1428 // Tail call to runtime. | 1140 // Tail call to runtime. |
| 1429 // Important invariant in CALLBACKS case: the code above must be | 1141 // Important invariant in CALLBACKS case: the code above must be |
| 1430 // structured to never clobber |receiver| register. | 1142 // structured to never clobber |receiver| register. |
| 1431 __ pop(scratch2); // return address | 1143 __ pop(scratch2); // return address |
| 1432 __ push(receiver); | 1144 __ push(receiver); |
| 1433 __ push(holder_reg); | 1145 __ push(holder_reg); |
| 1434 __ Move(holder_reg, Handle<AccessorInfo>(callback)); | 1146 __ Move(holder_reg, callback); |
| 1435 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); | 1147 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); |
| 1436 __ push(holder_reg); | 1148 __ push(holder_reg); |
| 1437 __ push(name_reg); | 1149 __ push(name_reg); |
| 1438 __ push(scratch2); // restore return address | 1150 __ push(scratch2); // restore return address |
| 1439 | 1151 |
| 1440 ExternalReference ref = | 1152 ExternalReference ref = |
| 1441 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), | 1153 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), |
| 1442 isolate()); | 1154 isolate()); |
| 1443 __ TailCallExternalReference(ref, 5, 1); | 1155 __ TailCallExternalReference(ref, 5, 1); |
| 1444 } | 1156 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1461 | 1173 |
| 1462 | 1174 |
| 1463 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { | 1175 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
| 1464 if (kind_ == Code::KEYED_CALL_IC) { | 1176 if (kind_ == Code::KEYED_CALL_IC) { |
| 1465 __ Cmp(rcx, name); | 1177 __ Cmp(rcx, name); |
| 1466 __ j(not_equal, miss); | 1178 __ j(not_equal, miss); |
| 1467 } | 1179 } |
| 1468 } | 1180 } |
| 1469 | 1181 |
| 1470 | 1182 |
| 1471 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1183 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, |
| 1472 JSObject* holder, | 1184 Handle<JSObject> holder, |
| 1473 String* name, | 1185 Handle<String> name, |
| 1474 Label* miss) { | 1186 Label* miss) { |
| 1475 ASSERT(holder->IsGlobalObject()); | 1187 ASSERT(holder->IsGlobalObject()); |
| 1476 | 1188 |
| 1477 // Get the number of arguments. | 1189 // Get the number of arguments. |
| 1478 const int argc = arguments().immediate(); | 1190 const int argc = arguments().immediate(); |
| 1479 | 1191 |
| 1480 // Get the receiver from the stack. | 1192 // Get the receiver from the stack. |
| 1481 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1193 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1482 | 1194 |
| 1483 // If the object is the holder then we know that it's a global | 1195 // If the object is the holder then we know that it's a global |
| 1484 // object which can only happen for contextual calls. In this case, | 1196 // object which can only happen for contextual calls. In this case, |
| 1485 // the receiver cannot be a smi. | 1197 // the receiver cannot be a smi. |
| 1486 if (object != holder) { | 1198 if (!object.is_identical_to(holder)) { |
| 1487 __ JumpIfSmi(rdx, miss); | 1199 __ JumpIfSmi(rdx, miss); |
| 1488 } | 1200 } |
| 1489 | 1201 |
| 1490 // Check that the maps haven't changed. | 1202 // Check that the maps haven't changed. |
| 1491 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); | 1203 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); |
| 1492 } | 1204 } |
| 1493 | 1205 |
| 1494 | 1206 |
| 1495 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1207 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1496 JSFunction* function, | 1208 Handle<JSGlobalPropertyCell> cell, |
| 1497 Label* miss) { | 1209 Handle<JSFunction> function, |
| 1210 Label* miss) { |
| 1498 // Get the value from the cell. | 1211 // Get the value from the cell. |
| 1499 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); | 1212 __ Move(rdi, cell); |
| 1500 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); | 1213 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); |
| 1501 | 1214 |
| 1502 // Check that the cell contains the same function. | 1215 // Check that the cell contains the same function. |
| 1503 if (heap()->InNewSpace(function)) { | 1216 if (heap()->InNewSpace(*function)) { |
| 1504 // We can't embed a pointer to a function in new space so we have | 1217 // We can't embed a pointer to a function in new space so we have |
| 1505 // to verify that the shared function info is unchanged. This has | 1218 // to verify that the shared function info is unchanged. This has |
| 1506 // the nice side effect that multiple closures based on the same | 1219 // the nice side effect that multiple closures based on the same |
| 1507 // function can all use this call IC. Before we load through the | 1220 // function can all use this call IC. Before we load through the |
| 1508 // function, we have to verify that it still is a function. | 1221 // function, we have to verify that it still is a function. |
| 1509 __ JumpIfSmi(rdi, miss); | 1222 __ JumpIfSmi(rdi, miss); |
| 1510 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); | 1223 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); |
| 1511 __ j(not_equal, miss); | 1224 __ j(not_equal, miss); |
| 1512 | 1225 |
| 1513 // Check the shared function info. Make sure it hasn't changed. | 1226 // Check the shared function info. Make sure it hasn't changed. |
| 1514 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | 1227 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
| 1515 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | 1228 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
| 1516 __ j(not_equal, miss); | |
| 1517 } else { | 1229 } else { |
| 1518 __ Cmp(rdi, Handle<JSFunction>(function)); | 1230 __ Cmp(rdi, function); |
| 1519 __ j(not_equal, miss); | |
| 1520 } | 1231 } |
| 1232 __ j(not_equal, miss); |
| 1521 } | 1233 } |
| 1522 | 1234 |
| 1523 | 1235 |
| 1524 void CallStubCompiler::GenerateMissBranch() { | 1236 void CallStubCompiler::GenerateMissBranch() { |
| 1525 Handle<Code> code = | 1237 Handle<Code> code = |
| 1526 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1238 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1527 kind_, | 1239 kind_, |
| 1528 extra_state_); | 1240 extra_state_); |
| 1529 __ Jump(code, RelocInfo::CODE_TARGET); | 1241 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1530 } | 1242 } |
| 1531 | 1243 |
| 1532 | 1244 |
| 1533 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 1534 // handlified. | |
| 1535 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { | |
| 1536 MaybeObject* maybe_obj = | |
| 1537 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), | |
| 1538 kind_, | |
| 1539 extra_state_); | |
| 1540 Object* obj; | |
| 1541 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 1542 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | |
| 1543 return obj; | |
| 1544 } | |
| 1545 | |
| 1546 | |
| 1547 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1245 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1548 Handle<JSObject> holder, | 1246 Handle<JSObject> holder, |
| 1549 int index, | 1247 int index, |
| 1550 Handle<String> name) { | 1248 Handle<String> name) { |
| 1551 // ----------- S t a t e ------------- | 1249 // ----------- S t a t e ------------- |
| 1552 // rcx : function name | 1250 // rcx : function name |
| 1553 // rsp[0] : return address | 1251 // rsp[0] : return address |
| 1554 // rsp[8] : argument argc | 1252 // rsp[8] : argument argc |
| 1555 // rsp[16] : argument argc - 1 | 1253 // rsp[16] : argument argc - 1 |
| 1556 // ... | 1254 // ... |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1595 | 1293 |
| 1596 // Handle call cache miss. | 1294 // Handle call cache miss. |
| 1597 __ bind(&miss); | 1295 __ bind(&miss); |
| 1598 GenerateMissBranch(); | 1296 GenerateMissBranch(); |
| 1599 | 1297 |
| 1600 // Return the generated code. | 1298 // Return the generated code. |
| 1601 return GetCode(FIELD, name); | 1299 return GetCode(FIELD, name); |
| 1602 } | 1300 } |
| 1603 | 1301 |
| 1604 | 1302 |
| 1605 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1303 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1606 JSObject* holder, | 1304 Handle<Object> object, |
| 1607 JSGlobalPropertyCell* cell, | 1305 Handle<JSObject> holder, |
| 1608 JSFunction* function, | 1306 Handle<JSGlobalPropertyCell> cell, |
| 1609 String* name) { | 1307 Handle<JSFunction> function, |
| 1308 Handle<String> name) { |
| 1610 // ----------- S t a t e ------------- | 1309 // ----------- S t a t e ------------- |
| 1611 // -- rcx : name | 1310 // -- rcx : name |
| 1612 // -- rsp[0] : return address | 1311 // -- rsp[0] : return address |
| 1613 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1312 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1614 // -- ... | 1313 // -- ... |
| 1615 // -- rsp[(argc + 1) * 8] : receiver | 1314 // -- rsp[(argc + 1) * 8] : receiver |
| 1616 // ----------------------------------- | 1315 // ----------------------------------- |
| 1617 | 1316 |
| 1618 // If object is not an array, bail out to regular call. | 1317 // If object is not an array, bail out to regular call. |
| 1619 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1318 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
| 1620 | 1319 |
| 1621 Label miss; | 1320 Label miss; |
| 1622 | 1321 GenerateNameCheck(name, &miss); |
| 1623 GenerateNameCheck(Handle<String>(name), &miss); | |
| 1624 | 1322 |
| 1625 // Get the receiver from the stack. | 1323 // Get the receiver from the stack. |
| 1626 const int argc = arguments().immediate(); | 1324 const int argc = arguments().immediate(); |
| 1627 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1325 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1628 | 1326 |
| 1629 // Check that the receiver isn't a smi. | 1327 // Check that the receiver isn't a smi. |
| 1630 __ JumpIfSmi(rdx, &miss); | 1328 __ JumpIfSmi(rdx, &miss); |
| 1631 | 1329 |
| 1632 CheckPrototypes(JSObject::cast(object), | 1330 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 1633 rdx, | 1331 name, &miss); |
| 1634 holder, | |
| 1635 rbx, | |
| 1636 rax, | |
| 1637 rdi, | |
| 1638 name, | |
| 1639 &miss); | |
| 1640 | 1332 |
| 1641 if (argc == 0) { | 1333 if (argc == 0) { |
| 1642 // Noop, return the length. | 1334 // Noop, return the length. |
| 1643 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1335 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
| 1644 __ ret((argc + 1) * kPointerSize); | 1336 __ ret((argc + 1) * kPointerSize); |
| 1645 } else { | 1337 } else { |
| 1646 Label call_builtin; | 1338 Label call_builtin; |
| 1647 | 1339 |
| 1648 // Get the elements array of the object. | 1340 // Get the elements array of the object. |
| 1649 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1341 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1691 | 1383 |
| 1692 // Save new length. | 1384 // Save new length. |
| 1693 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1385 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
| 1694 | 1386 |
| 1695 // Push the element. | 1387 // Push the element. |
| 1696 __ lea(rdx, FieldOperand(rbx, | 1388 __ lea(rdx, FieldOperand(rbx, |
| 1697 rax, times_pointer_size, | 1389 rax, times_pointer_size, |
| 1698 FixedArray::kHeaderSize - argc * kPointerSize)); | 1390 FixedArray::kHeaderSize - argc * kPointerSize)); |
| 1699 __ movq(Operand(rdx, 0), rcx); | 1391 __ movq(Operand(rdx, 0), rcx); |
| 1700 | 1392 |
| 1701 __ RecordWrite( | 1393 __ RecordWrite(rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
| 1702 rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 1394 OMIT_SMI_CHECK); |
| 1703 | 1395 |
| 1704 __ Integer32ToSmi(rax, rax); // Return new length as smi. | 1396 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
| 1705 __ ret((argc + 1) * kPointerSize); | 1397 __ ret((argc + 1) * kPointerSize); |
| 1706 | 1398 |
| 1707 __ bind(&attempt_to_grow_elements); | 1399 __ bind(&attempt_to_grow_elements); |
| 1708 if (!FLAG_inline_new) { | 1400 if (!FLAG_inline_new) { |
| 1709 __ jmp(&call_builtin); | 1401 __ jmp(&call_builtin); |
| 1710 } | 1402 } |
| 1711 | 1403 |
| 1712 __ movq(rdi, Operand(rsp, argc * kPointerSize)); | 1404 __ movq(rdi, Operand(rsp, argc * kPointerSize)); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1772 } | 1464 } |
| 1773 | 1465 |
| 1774 __ bind(&call_builtin); | 1466 __ bind(&call_builtin); |
| 1775 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1467 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
| 1776 isolate()), | 1468 isolate()), |
| 1777 argc + 1, | 1469 argc + 1, |
| 1778 1); | 1470 1); |
| 1779 } | 1471 } |
| 1780 | 1472 |
| 1781 __ bind(&miss); | 1473 __ bind(&miss); |
| 1782 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1474 GenerateMissBranch(); |
| 1783 if (maybe_result->IsFailure()) return maybe_result; | |
| 1784 | 1475 |
| 1785 // Return the generated code. | 1476 // Return the generated code. |
| 1786 return TryGetCode(function); | 1477 return GetCode(function); |
| 1787 } | 1478 } |
| 1788 | 1479 |
| 1789 | 1480 |
| 1790 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1481 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1791 JSObject* holder, | 1482 Handle<Object> object, |
| 1792 JSGlobalPropertyCell* cell, | 1483 Handle<JSObject> holder, |
| 1793 JSFunction* function, | 1484 Handle<JSGlobalPropertyCell> cell, |
| 1794 String* name) { | 1485 Handle<JSFunction> function, |
| 1486 Handle<String> name) { |
| 1795 // ----------- S t a t e ------------- | 1487 // ----------- S t a t e ------------- |
| 1796 // -- rcx : name | 1488 // -- rcx : name |
| 1797 // -- rsp[0] : return address | 1489 // -- rsp[0] : return address |
| 1798 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1490 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1799 // -- ... | 1491 // -- ... |
| 1800 // -- rsp[(argc + 1) * 8] : receiver | 1492 // -- rsp[(argc + 1) * 8] : receiver |
| 1801 // ----------------------------------- | 1493 // ----------------------------------- |
| 1802 | 1494 |
| 1803 // If object is not an array, bail out to regular call. | 1495 // If object is not an array, bail out to regular call. |
| 1804 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1496 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
| 1805 | 1497 |
| 1806 Label miss, return_undefined, call_builtin; | 1498 Label miss, return_undefined, call_builtin; |
| 1807 | 1499 GenerateNameCheck(name, &miss); |
| 1808 GenerateNameCheck(Handle<String>(name), &miss); | |
| 1809 | 1500 |
| 1810 // Get the receiver from the stack. | 1501 // Get the receiver from the stack. |
| 1811 const int argc = arguments().immediate(); | 1502 const int argc = arguments().immediate(); |
| 1812 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1503 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1813 | 1504 |
| 1814 // Check that the receiver isn't a smi. | 1505 // Check that the receiver isn't a smi. |
| 1815 __ JumpIfSmi(rdx, &miss); | 1506 __ JumpIfSmi(rdx, &miss); |
| 1816 | 1507 |
| 1817 CheckPrototypes(JSObject::cast(object), rdx, | 1508 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 1818 holder, rbx, | 1509 name, &miss); |
| 1819 rax, rdi, name, &miss); | |
| 1820 | 1510 |
| 1821 // Get the elements array of the object. | 1511 // Get the elements array of the object. |
| 1822 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1512 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 1823 | 1513 |
| 1824 // Check that the elements are in fast mode and writable. | 1514 // Check that the elements are in fast mode and writable. |
| 1825 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1515 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
| 1826 Heap::kFixedArrayMapRootIndex); | 1516 Heap::kFixedArrayMapRootIndex); |
| 1827 __ j(not_equal, &call_builtin); | 1517 __ j(not_equal, &call_builtin); |
| 1828 | 1518 |
| 1829 // Get the array's length into rcx and calculate new length. | 1519 // Get the array's length into rcx and calculate new length. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1855 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1545 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1856 __ ret((argc + 1) * kPointerSize); | 1546 __ ret((argc + 1) * kPointerSize); |
| 1857 | 1547 |
| 1858 __ bind(&call_builtin); | 1548 __ bind(&call_builtin); |
| 1859 __ TailCallExternalReference( | 1549 __ TailCallExternalReference( |
| 1860 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1550 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 1861 argc + 1, | 1551 argc + 1, |
| 1862 1); | 1552 1); |
| 1863 | 1553 |
| 1864 __ bind(&miss); | 1554 __ bind(&miss); |
| 1865 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1555 GenerateMissBranch(); |
| 1866 if (maybe_result->IsFailure()) return maybe_result; | |
| 1867 | 1556 |
| 1868 // Return the generated code. | 1557 // Return the generated code. |
| 1869 return TryGetCode(function); | 1558 return GetCode(function); |
| 1870 } | 1559 } |
| 1871 | 1560 |
| 1872 | 1561 |
| 1873 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1562 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 1874 Object* object, | 1563 Handle<Object> object, |
| 1875 JSObject* holder, | 1564 Handle<JSObject> holder, |
| 1876 JSGlobalPropertyCell* cell, | 1565 Handle<JSGlobalPropertyCell> cell, |
| 1877 JSFunction* function, | 1566 Handle<JSFunction> function, |
| 1878 String* name) { | 1567 Handle<String> name) { |
| 1879 // ----------- S t a t e ------------- | 1568 // ----------- S t a t e ------------- |
| 1880 // -- rcx : function name | 1569 // -- rcx : function name |
| 1881 // -- rsp[0] : return address | 1570 // -- rsp[0] : return address |
| 1882 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1571 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1883 // -- ... | 1572 // -- ... |
| 1884 // -- rsp[(argc + 1) * 8] : receiver | 1573 // -- rsp[(argc + 1) * 8] : receiver |
| 1885 // ----------------------------------- | 1574 // ----------------------------------- |
| 1886 | 1575 |
| 1887 // If object is not a string, bail out to regular call. | 1576 // If object is not a string, bail out to regular call. |
| 1888 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1577 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 1889 | 1578 |
| 1890 const int argc = arguments().immediate(); | 1579 const int argc = arguments().immediate(); |
| 1891 | 1580 |
| 1892 Label miss; | 1581 Label miss; |
| 1893 Label name_miss; | 1582 Label name_miss; |
| 1894 Label index_out_of_range; | 1583 Label index_out_of_range; |
| 1895 Label* index_out_of_range_label = &index_out_of_range; | 1584 Label* index_out_of_range_label = &index_out_of_range; |
| 1896 | |
| 1897 if (kind_ == Code::CALL_IC && | 1585 if (kind_ == Code::CALL_IC && |
| 1898 (CallICBase::StringStubState::decode(extra_state_) == | 1586 (CallICBase::StringStubState::decode(extra_state_) == |
| 1899 DEFAULT_STRING_STUB)) { | 1587 DEFAULT_STRING_STUB)) { |
| 1900 index_out_of_range_label = &miss; | 1588 index_out_of_range_label = &miss; |
| 1901 } | 1589 } |
| 1902 | 1590 GenerateNameCheck(name, &name_miss); |
| 1903 GenerateNameCheck(Handle<String>(name), &name_miss); | |
| 1904 | 1591 |
| 1905 // Check that the maps starting from the prototype haven't changed. | 1592 // Check that the maps starting from the prototype haven't changed. |
| 1906 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1593 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1907 Context::STRING_FUNCTION_INDEX, | 1594 Context::STRING_FUNCTION_INDEX, |
| 1908 rax, | 1595 rax, |
| 1909 &miss); | 1596 &miss); |
| 1910 ASSERT(object != holder); | 1597 ASSERT(!object.is_identical_to(holder)); |
| 1911 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 1598 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 1912 rbx, rdx, rdi, name, &miss); | 1599 rax, holder, rbx, rdx, rdi, name, &miss); |
| 1913 | 1600 |
| 1914 Register receiver = rbx; | 1601 Register receiver = rbx; |
| 1915 Register index = rdi; | 1602 Register index = rdi; |
| 1916 Register scratch = rdx; | 1603 Register scratch = rdx; |
| 1917 Register result = rax; | 1604 Register result = rax; |
| 1918 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); | 1605 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1919 if (argc > 0) { | 1606 if (argc > 0) { |
| 1920 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); | 1607 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); |
| 1921 } else { | 1608 } else { |
| 1922 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1609 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 1923 } | 1610 } |
| 1924 | 1611 |
| 1925 StringCharCodeAtGenerator char_code_at_generator(receiver, | 1612 StringCharCodeAtGenerator generator(receiver, |
| 1926 index, | 1613 index, |
| 1927 scratch, | 1614 scratch, |
| 1928 result, | 1615 result, |
| 1929 &miss, // When not a string. | 1616 &miss, // When not a string. |
| 1930 &miss, // When not a number. | 1617 &miss, // When not a number. |
| 1931 index_out_of_range_label, | 1618 index_out_of_range_label, |
| 1932 STRING_INDEX_IS_NUMBER); | 1619 STRING_INDEX_IS_NUMBER); |
| 1933 char_code_at_generator.GenerateFast(masm()); | 1620 generator.GenerateFast(masm()); |
| 1934 __ ret((argc + 1) * kPointerSize); | 1621 __ ret((argc + 1) * kPointerSize); |
| 1935 | 1622 |
| 1936 StubRuntimeCallHelper call_helper; | 1623 StubRuntimeCallHelper call_helper; |
| 1937 char_code_at_generator.GenerateSlow(masm(), call_helper); | 1624 generator.GenerateSlow(masm(), call_helper); |
| 1938 | 1625 |
| 1939 if (index_out_of_range.is_linked()) { | 1626 if (index_out_of_range.is_linked()) { |
| 1940 __ bind(&index_out_of_range); | 1627 __ bind(&index_out_of_range); |
| 1941 __ LoadRoot(rax, Heap::kNanValueRootIndex); | 1628 __ LoadRoot(rax, Heap::kNanValueRootIndex); |
| 1942 __ ret((argc + 1) * kPointerSize); | 1629 __ ret((argc + 1) * kPointerSize); |
| 1943 } | 1630 } |
| 1944 | 1631 |
| 1945 __ bind(&miss); | 1632 __ bind(&miss); |
| 1946 // Restore function name in rcx. | 1633 // Restore function name in rcx. |
| 1947 __ Move(rcx, Handle<String>(name)); | 1634 __ Move(rcx, name); |
| 1948 __ bind(&name_miss); | 1635 __ bind(&name_miss); |
| 1949 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1636 GenerateMissBranch(); |
| 1950 if (maybe_result->IsFailure()) return maybe_result; | |
| 1951 | 1637 |
| 1952 // Return the generated code. | 1638 // Return the generated code. |
| 1953 return TryGetCode(function); | 1639 return GetCode(function); |
| 1954 } | 1640 } |
| 1955 | 1641 |
| 1956 | 1642 |
| 1957 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1643 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 1958 Object* object, | 1644 Handle<Object> object, |
| 1959 JSObject* holder, | 1645 Handle<JSObject> holder, |
| 1960 JSGlobalPropertyCell* cell, | 1646 Handle<JSGlobalPropertyCell> cell, |
| 1961 JSFunction* function, | 1647 Handle<JSFunction> function, |
| 1962 String* name) { | 1648 Handle<String> name) { |
| 1963 // ----------- S t a t e ------------- | 1649 // ----------- S t a t e ------------- |
| 1964 // -- rcx : function name | 1650 // -- rcx : function name |
| 1965 // -- rsp[0] : return address | 1651 // -- rsp[0] : return address |
| 1966 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1652 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1967 // -- ... | 1653 // -- ... |
| 1968 // -- rsp[(argc + 1) * 8] : receiver | 1654 // -- rsp[(argc + 1) * 8] : receiver |
| 1969 // ----------------------------------- | 1655 // ----------------------------------- |
| 1970 | 1656 |
| 1971 // If object is not a string, bail out to regular call. | 1657 // If object is not a string, bail out to regular call. |
| 1972 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1658 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 1973 | 1659 |
| 1974 const int argc = arguments().immediate(); | 1660 const int argc = arguments().immediate(); |
| 1975 | |
| 1976 Label miss; | 1661 Label miss; |
| 1977 Label name_miss; | 1662 Label name_miss; |
| 1978 Label index_out_of_range; | 1663 Label index_out_of_range; |
| 1979 Label* index_out_of_range_label = &index_out_of_range; | 1664 Label* index_out_of_range_label = &index_out_of_range; |
| 1980 | |
| 1981 if (kind_ == Code::CALL_IC && | 1665 if (kind_ == Code::CALL_IC && |
| 1982 (CallICBase::StringStubState::decode(extra_state_) == | 1666 (CallICBase::StringStubState::decode(extra_state_) == |
| 1983 DEFAULT_STRING_STUB)) { | 1667 DEFAULT_STRING_STUB)) { |
| 1984 index_out_of_range_label = &miss; | 1668 index_out_of_range_label = &miss; |
| 1985 } | 1669 } |
| 1986 | 1670 GenerateNameCheck(name, &name_miss); |
| 1987 GenerateNameCheck(Handle<String>(name), &name_miss); | |
| 1988 | 1671 |
| 1989 // Check that the maps starting from the prototype haven't changed. | 1672 // Check that the maps starting from the prototype haven't changed. |
| 1990 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1673 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1991 Context::STRING_FUNCTION_INDEX, | 1674 Context::STRING_FUNCTION_INDEX, |
| 1992 rax, | 1675 rax, |
| 1993 &miss); | 1676 &miss); |
| 1994 ASSERT(object != holder); | 1677 ASSERT(!object.is_identical_to(holder)); |
| 1995 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 1678 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 1996 rbx, rdx, rdi, name, &miss); | 1679 rax, holder, rbx, rdx, rdi, name, &miss); |
| 1997 | 1680 |
| 1998 Register receiver = rax; | 1681 Register receiver = rax; |
| 1999 Register index = rdi; | 1682 Register index = rdi; |
| 2000 Register scratch1 = rbx; | 1683 Register scratch1 = rbx; |
| 2001 Register scratch2 = rdx; | 1684 Register scratch2 = rdx; |
| 2002 Register result = rax; | 1685 Register result = rax; |
| 2003 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); | 1686 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2004 if (argc > 0) { | 1687 if (argc > 0) { |
| 2005 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); | 1688 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); |
| 2006 } else { | 1689 } else { |
| 2007 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1690 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2008 } | 1691 } |
| 2009 | 1692 |
| 2010 StringCharAtGenerator char_at_generator(receiver, | 1693 StringCharAtGenerator generator(receiver, |
| 2011 index, | 1694 index, |
| 2012 scratch1, | 1695 scratch1, |
| 2013 scratch2, | 1696 scratch2, |
| 2014 result, | 1697 result, |
| 2015 &miss, // When not a string. | 1698 &miss, // When not a string. |
| 2016 &miss, // When not a number. | 1699 &miss, // When not a number. |
| 2017 index_out_of_range_label, | 1700 index_out_of_range_label, |
| 2018 STRING_INDEX_IS_NUMBER); | 1701 STRING_INDEX_IS_NUMBER); |
| 2019 char_at_generator.GenerateFast(masm()); | 1702 generator.GenerateFast(masm()); |
| 2020 __ ret((argc + 1) * kPointerSize); | 1703 __ ret((argc + 1) * kPointerSize); |
| 2021 | 1704 |
| 2022 StubRuntimeCallHelper call_helper; | 1705 StubRuntimeCallHelper call_helper; |
| 2023 char_at_generator.GenerateSlow(masm(), call_helper); | 1706 generator.GenerateSlow(masm(), call_helper); |
| 2024 | 1707 |
| 2025 if (index_out_of_range.is_linked()) { | 1708 if (index_out_of_range.is_linked()) { |
| 2026 __ bind(&index_out_of_range); | 1709 __ bind(&index_out_of_range); |
| 2027 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); | 1710 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); |
| 2028 __ ret((argc + 1) * kPointerSize); | 1711 __ ret((argc + 1) * kPointerSize); |
| 2029 } | 1712 } |
| 2030 | |
| 2031 __ bind(&miss); | 1713 __ bind(&miss); |
| 2032 // Restore function name in rcx. | 1714 // Restore function name in rcx. |
| 2033 __ Move(rcx, Handle<String>(name)); | 1715 __ Move(rcx, name); |
| 2034 __ bind(&name_miss); | 1716 __ bind(&name_miss); |
| 2035 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1717 GenerateMissBranch(); |
| 2036 if (maybe_result->IsFailure()) return maybe_result; | |
| 2037 | 1718 |
| 2038 // Return the generated code. | 1719 // Return the generated code. |
| 2039 return TryGetCode(function); | 1720 return GetCode(function); |
| 2040 } | 1721 } |
| 2041 | 1722 |
| 2042 | 1723 |
| 2043 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 1724 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2044 Object* object, | 1725 Handle<Object> object, |
| 2045 JSObject* holder, | 1726 Handle<JSObject> holder, |
| 2046 JSGlobalPropertyCell* cell, | 1727 Handle<JSGlobalPropertyCell> cell, |
| 2047 JSFunction* function, | 1728 Handle<JSFunction> function, |
| 2048 String* name) { | 1729 Handle<String> name) { |
| 2049 // ----------- S t a t e ------------- | 1730 // ----------- S t a t e ------------- |
| 2050 // -- rcx : function name | 1731 // -- rcx : function name |
| 2051 // -- rsp[0] : return address | 1732 // -- rsp[0] : return address |
| 2052 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1733 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 2053 // -- ... | 1734 // -- ... |
| 2054 // -- rsp[(argc + 1) * 8] : receiver | 1735 // -- rsp[(argc + 1) * 8] : receiver |
| 2055 // ----------------------------------- | 1736 // ----------------------------------- |
| 2056 | 1737 |
| 2057 const int argc = arguments().immediate(); | |
| 2058 | |
| 2059 // If the object is not a JSObject or we got an unexpected number of | 1738 // If the object is not a JSObject or we got an unexpected number of |
| 2060 // arguments, bail out to the regular call. | 1739 // arguments, bail out to the regular call. |
| 2061 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1740 const int argc = arguments().immediate(); |
| 1741 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2062 | 1742 |
| 2063 Label miss; | 1743 Label miss; |
| 2064 GenerateNameCheck(Handle<String>(name), &miss); | 1744 GenerateNameCheck(name, &miss); |
| 2065 | 1745 |
| 2066 if (cell == NULL) { | 1746 if (cell.is_null()) { |
| 2067 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 1747 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 2068 | |
| 2069 __ JumpIfSmi(rdx, &miss); | 1748 __ JumpIfSmi(rdx, &miss); |
| 2070 | 1749 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2071 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, | 1750 name, &miss); |
| 2072 &miss); | |
| 2073 } else { | 1751 } else { |
| 2074 ASSERT(cell->value() == function); | 1752 ASSERT(cell->value() == *function); |
| 2075 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1753 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1754 &miss); |
| 2076 GenerateLoadFunctionFromCell(cell, function, &miss); | 1755 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2077 } | 1756 } |
| 2078 | 1757 |
| 2079 // Load the char code argument. | 1758 // Load the char code argument. |
| 2080 Register code = rbx; | 1759 Register code = rbx; |
| 2081 __ movq(code, Operand(rsp, 1 * kPointerSize)); | 1760 __ movq(code, Operand(rsp, 1 * kPointerSize)); |
| 2082 | 1761 |
| 2083 // Check the code is a smi. | 1762 // Check the code is a smi. |
| 2084 Label slow; | 1763 Label slow; |
| 2085 __ JumpIfNotSmi(code, &slow); | 1764 __ JumpIfNotSmi(code, &slow); |
| 2086 | 1765 |
| 2087 // Convert the smi code to uint16. | 1766 // Convert the smi code to uint16. |
| 2088 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); | 1767 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); |
| 2089 | 1768 |
| 2090 StringCharFromCodeGenerator char_from_code_generator(code, rax); | 1769 StringCharFromCodeGenerator generator(code, rax); |
| 2091 char_from_code_generator.GenerateFast(masm()); | 1770 generator.GenerateFast(masm()); |
| 2092 __ ret(2 * kPointerSize); | 1771 __ ret(2 * kPointerSize); |
| 2093 | 1772 |
| 2094 StubRuntimeCallHelper call_helper; | 1773 StubRuntimeCallHelper call_helper; |
| 2095 char_from_code_generator.GenerateSlow(masm(), call_helper); | 1774 generator.GenerateSlow(masm(), call_helper); |
| 2096 | 1775 |
| 2097 // Tail call the full function. We do not have to patch the receiver | 1776 // Tail call the full function. We do not have to patch the receiver |
| 2098 // because the function makes no use of it. | 1777 // because the function makes no use of it. |
| 2099 __ bind(&slow); | 1778 __ bind(&slow); |
| 2100 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1779 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2101 ? CALL_AS_FUNCTION | 1780 ? CALL_AS_FUNCTION |
| 2102 : CALL_AS_METHOD; | 1781 : CALL_AS_METHOD; |
| 2103 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 1782 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2104 NullCallWrapper(), call_kind); | 1783 NullCallWrapper(), call_kind); |
| 2105 | 1784 |
| 2106 __ bind(&miss); | 1785 __ bind(&miss); |
| 2107 // rcx: function name. | 1786 // rcx: function name. |
| 2108 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1787 GenerateMissBranch(); |
| 2109 if (maybe_result->IsFailure()) return maybe_result; | |
| 2110 | 1788 |
| 2111 // Return the generated code. | 1789 // Return the generated code. |
| 2112 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 1790 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
| 2113 } | 1791 } |
| 2114 | 1792 |
| 2115 | 1793 |
| 2116 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 1794 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2117 JSObject* holder, | 1795 Handle<Object> object, |
| 2118 JSGlobalPropertyCell* cell, | 1796 Handle<JSObject> holder, |
| 2119 JSFunction* function, | 1797 Handle<JSGlobalPropertyCell> cell, |
| 2120 String* name) { | 1798 Handle<JSFunction> function, |
| 1799 Handle<String> name) { |
| 2121 // TODO(872): implement this. | 1800 // TODO(872): implement this. |
| 2122 return heap()->undefined_value(); | 1801 return Handle<Code>::null(); |
| 2123 } | 1802 } |
| 2124 | 1803 |
| 2125 | 1804 |
| 2126 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 1805 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2127 JSObject* holder, | 1806 Handle<Object> object, |
| 2128 JSGlobalPropertyCell* cell, | 1807 Handle<JSObject> holder, |
| 2129 JSFunction* function, | 1808 Handle<JSGlobalPropertyCell> cell, |
| 2130 String* name) { | 1809 Handle<JSFunction> function, |
| 1810 Handle<String> name) { |
| 2131 // ----------- S t a t e ------------- | 1811 // ----------- S t a t e ------------- |
| 2132 // -- rcx : function name | 1812 // -- rcx : function name |
| 2133 // -- rsp[0] : return address | 1813 // -- rsp[0] : return address |
| 2134 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1814 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 2135 // -- ... | 1815 // -- ... |
| 2136 // -- rsp[(argc + 1) * 8] : receiver | 1816 // -- rsp[(argc + 1) * 8] : receiver |
| 2137 // ----------------------------------- | 1817 // ----------------------------------- |
| 2138 | 1818 |
| 2139 const int argc = arguments().immediate(); | |
| 2140 | |
| 2141 // If the object is not a JSObject or we got an unexpected number of | 1819 // If the object is not a JSObject or we got an unexpected number of |
| 2142 // arguments, bail out to the regular call. | 1820 // arguments, bail out to the regular call. |
| 2143 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1821 const int argc = arguments().immediate(); |
| 1822 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2144 | 1823 |
| 2145 Label miss; | 1824 Label miss; |
| 2146 GenerateNameCheck(Handle<String>(name), &miss); | 1825 GenerateNameCheck(name, &miss); |
| 2147 | 1826 |
| 2148 if (cell == NULL) { | 1827 if (cell.is_null()) { |
| 2149 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 1828 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 2150 | |
| 2151 __ JumpIfSmi(rdx, &miss); | 1829 __ JumpIfSmi(rdx, &miss); |
| 2152 | 1830 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2153 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, | 1831 name, &miss); |
| 2154 &miss); | |
| 2155 } else { | 1832 } else { |
| 2156 ASSERT(cell->value() == function); | 1833 ASSERT(cell->value() == *function); |
| 2157 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1834 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1835 &miss); |
| 2158 GenerateLoadFunctionFromCell(cell, function, &miss); | 1836 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2159 } | 1837 } |
| 2160 | |
| 2161 // Load the (only) argument into rax. | 1838 // Load the (only) argument into rax. |
| 2162 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 1839 __ movq(rax, Operand(rsp, 1 * kPointerSize)); |
| 2163 | 1840 |
| 2164 // Check if the argument is a smi. | 1841 // Check if the argument is a smi. |
| 2165 Label not_smi; | 1842 Label not_smi; |
| 2166 STATIC_ASSERT(kSmiTag == 0); | 1843 STATIC_ASSERT(kSmiTag == 0); |
| 2167 __ JumpIfNotSmi(rax, ¬_smi); | 1844 __ JumpIfNotSmi(rax, ¬_smi); |
| 2168 __ SmiToInteger32(rax, rax); | 1845 __ SmiToInteger32(rax, rax); |
| 2169 | 1846 |
| 2170 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 | 1847 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2215 // because the function makes no use of it. | 1892 // because the function makes no use of it. |
| 2216 __ bind(&slow); | 1893 __ bind(&slow); |
| 2217 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1894 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2218 ? CALL_AS_FUNCTION | 1895 ? CALL_AS_FUNCTION |
| 2219 : CALL_AS_METHOD; | 1896 : CALL_AS_METHOD; |
| 2220 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 1897 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2221 NullCallWrapper(), call_kind); | 1898 NullCallWrapper(), call_kind); |
| 2222 | 1899 |
| 2223 __ bind(&miss); | 1900 __ bind(&miss); |
| 2224 // rcx: function name. | 1901 // rcx: function name. |
| 2225 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1902 GenerateMissBranch(); |
| 2226 if (maybe_result->IsFailure()) return maybe_result; | |
| 2227 | 1903 |
| 2228 // Return the generated code. | 1904 // Return the generated code. |
| 2229 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 1905 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
| 2230 } | 1906 } |
| 2231 | 1907 |
| 2232 | 1908 |
| 2233 MaybeObject* CallStubCompiler::CompileFastApiCall( | 1909 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2234 const CallOptimization& optimization, | 1910 const CallOptimization& optimization, |
| 2235 Object* object, | 1911 Handle<Object> object, |
| 2236 JSObject* holder, | 1912 Handle<JSObject> holder, |
| 2237 JSGlobalPropertyCell* cell, | 1913 Handle<JSGlobalPropertyCell> cell, |
| 2238 JSFunction* function, | 1914 Handle<JSFunction> function, |
| 2239 String* name) { | 1915 Handle<String> name) { |
| 2240 ASSERT(optimization.is_simple_api_call()); | 1916 ASSERT(optimization.is_simple_api_call()); |
| 2241 // Bail out if object is a global object as we don't want to | 1917 // Bail out if object is a global object as we don't want to |
| 2242 // repatch it to global receiver. | 1918 // repatch it to global receiver. |
| 2243 if (object->IsGlobalObject()) return heap()->undefined_value(); | 1919 if (object->IsGlobalObject()) return Handle<Code>::null(); |
| 2244 if (cell != NULL) return heap()->undefined_value(); | 1920 if (!cell.is_null()) return Handle<Code>::null(); |
| 2245 if (!object->IsJSObject()) return heap()->undefined_value(); | 1921 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 2246 int depth = optimization.GetPrototypeDepthOfExpectedType( | 1922 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2247 JSObject::cast(object), holder); | 1923 Handle<JSObject>::cast(object), holder); |
| 2248 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 1924 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); |
| 2249 | 1925 |
| 2250 Label miss, miss_before_stack_reserved; | 1926 Label miss, miss_before_stack_reserved; |
| 2251 | 1927 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2252 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); | |
| 2253 | 1928 |
| 2254 // Get the receiver from the stack. | 1929 // Get the receiver from the stack. |
| 2255 const int argc = arguments().immediate(); | 1930 const int argc = arguments().immediate(); |
| 2256 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1931 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2257 | 1932 |
| 2258 // Check that the receiver isn't a smi. | 1933 // Check that the receiver isn't a smi. |
| 2259 __ JumpIfSmi(rdx, &miss_before_stack_reserved); | 1934 __ JumpIfSmi(rdx, &miss_before_stack_reserved); |
| 2260 | 1935 |
| 2261 Counters* counters = isolate()->counters(); | 1936 Counters* counters = isolate()->counters(); |
| 2262 __ IncrementCounter(counters->call_const(), 1); | 1937 __ IncrementCounter(counters->call_const(), 1); |
| 2263 __ IncrementCounter(counters->call_const_fast_api(), 1); | 1938 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2264 | 1939 |
| 2265 // Allocate space for v8::Arguments implicit values. Must be initialized | 1940 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2266 // before calling any runtime function. | 1941 // before calling any runtime function. |
| 2267 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 1942 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2268 | 1943 |
| 2269 // Check that the maps haven't changed and find a Holder as a side effect. | 1944 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2270 CheckPrototypes(JSObject::cast(object), rdx, holder, | 1945 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2271 rbx, rax, rdi, name, depth, &miss); | 1946 name, depth, &miss); |
| 2272 | 1947 |
| 2273 // Move the return address on top of the stack. | 1948 // Move the return address on top of the stack. |
| 2274 __ movq(rax, Operand(rsp, 3 * kPointerSize)); | 1949 __ movq(rax, Operand(rsp, 3 * kPointerSize)); |
| 2275 __ movq(Operand(rsp, 0 * kPointerSize), rax); | 1950 __ movq(Operand(rsp, 0 * kPointerSize), rax); |
| 2276 | 1951 |
| 2277 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 1952 GenerateFastApiCall(masm(), optimization, argc); |
| 2278 if (result->IsFailure()) return result; | |
| 2279 | 1953 |
| 2280 __ bind(&miss); | 1954 __ bind(&miss); |
| 2281 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 1955 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2282 | 1956 |
| 2283 __ bind(&miss_before_stack_reserved); | 1957 __ bind(&miss_before_stack_reserved); |
| 2284 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1958 GenerateMissBranch(); |
| 2285 if (maybe_result->IsFailure()) return maybe_result; | |
| 2286 | 1959 |
| 2287 // Return the generated code. | 1960 // Return the generated code. |
| 2288 return TryGetCode(function); | 1961 return GetCode(function); |
| 2289 } | 1962 } |
| 2290 | 1963 |
| 2291 | 1964 |
| 2292 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 1965 Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, |
| 2293 JSObject* holder, | 1966 Handle<JSObject> holder, |
| 2294 JSFunction* function, | 1967 Handle<JSFunction> function, |
| 2295 String* name, | 1968 Handle<String> name, |
| 2296 CheckType check) { | 1969 CheckType check) { |
| 2297 // ----------- S t a t e ------------- | 1970 // ----------- S t a t e ------------- |
| 2298 // rcx : function name | 1971 // rcx : function name |
| 2299 // rsp[0] : return address | 1972 // rsp[0] : return address |
| 2300 // rsp[8] : argument argc | 1973 // rsp[8] : argument argc |
| 2301 // rsp[16] : argument argc - 1 | 1974 // rsp[16] : argument argc - 1 |
| 2302 // ... | 1975 // ... |
| 2303 // rsp[argc * 8] : argument 1 | 1976 // rsp[argc * 8] : argument 1 |
| 2304 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1977 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2305 // ----------------------------------- | 1978 // ----------------------------------- |
| 2306 | 1979 |
| 2307 if (HasCustomCallGenerator(function)) { | 1980 if (HasCustomCallGenerator(function)) { |
| 2308 MaybeObject* maybe_result = CompileCustomCall( | 1981 Handle<Code> code = CompileCustomCall(object, holder, |
| 2309 object, holder, NULL, function, name); | 1982 Handle<JSGlobalPropertyCell>::null(), |
| 2310 Object* result; | 1983 function, name); |
| 2311 if (!maybe_result->ToObject(&result)) return maybe_result; | 1984 // A null handle means bail out to the regular compiler code below. |
| 2312 // undefined means bail out to regular compiler. | 1985 if (!code.is_null()) return code; |
| 2313 if (!result->IsUndefined()) return result; | |
| 2314 } | 1986 } |
| 2315 | 1987 |
| 2316 Label miss; | 1988 Label miss; |
| 2317 | 1989 GenerateNameCheck(name, &miss); |
| 2318 GenerateNameCheck(Handle<String>(name), &miss); | |
| 2319 | 1990 |
| 2320 // Get the receiver from the stack. | 1991 // Get the receiver from the stack. |
| 2321 const int argc = arguments().immediate(); | 1992 const int argc = arguments().immediate(); |
| 2322 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1993 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2323 | 1994 |
| 2324 // Check that the receiver isn't a smi. | 1995 // Check that the receiver isn't a smi. |
| 2325 if (check != NUMBER_CHECK) { | 1996 if (check != NUMBER_CHECK) { |
| 2326 __ JumpIfSmi(rdx, &miss); | 1997 __ JumpIfSmi(rdx, &miss); |
| 2327 } | 1998 } |
| 2328 | 1999 |
| 2329 // Make sure that it's okay not to patch the on stack receiver | 2000 // Make sure that it's okay not to patch the on stack receiver |
| 2330 // unless we're doing a receiver map check. | 2001 // unless we're doing a receiver map check. |
| 2331 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2002 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2332 | 2003 |
| 2333 Counters* counters = isolate()->counters(); | 2004 Counters* counters = isolate()->counters(); |
| 2334 SharedFunctionInfo* function_info = function->shared(); | |
| 2335 switch (check) { | 2005 switch (check) { |
| 2336 case RECEIVER_MAP_CHECK: | 2006 case RECEIVER_MAP_CHECK: |
| 2337 __ IncrementCounter(counters->call_const(), 1); | 2007 __ IncrementCounter(counters->call_const(), 1); |
| 2338 | 2008 |
| 2339 // Check that the maps haven't changed. | 2009 // Check that the maps haven't changed. |
| 2340 CheckPrototypes(JSObject::cast(object), rdx, holder, | 2010 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, |
| 2341 rbx, rax, rdi, name, &miss); | 2011 rdi, name, &miss); |
| 2342 | 2012 |
| 2343 // Patch the receiver on the stack with the global proxy if | 2013 // Patch the receiver on the stack with the global proxy if |
| 2344 // necessary. | 2014 // necessary. |
| 2345 if (object->IsGlobalObject()) { | 2015 if (object->IsGlobalObject()) { |
| 2346 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2016 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2347 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2017 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2348 } | 2018 } |
| 2349 break; | 2019 break; |
| 2350 | 2020 |
| 2351 case STRING_CHECK: | 2021 case STRING_CHECK: |
| 2352 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2022 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
| 2353 // Calling non-strict non-builtins with a value as the receiver | |
| 2354 // requires boxing. | |
| 2355 __ jmp(&miss); | |
| 2356 } else { | |
| 2357 // Check that the object is a two-byte string or a symbol. | 2023 // Check that the object is a two-byte string or a symbol. |
| 2358 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); | 2024 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); |
| 2359 __ j(above_equal, &miss); | 2025 __ j(above_equal, &miss); |
| 2360 // Check that the maps starting from the prototype haven't changed. | 2026 // Check that the maps starting from the prototype haven't changed. |
| 2361 GenerateDirectLoadGlobalFunctionPrototype( | 2027 GenerateDirectLoadGlobalFunctionPrototype( |
| 2362 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); | 2028 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); |
| 2363 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2029 CheckPrototypes( |
| 2364 rbx, rdx, rdi, name, &miss); | 2030 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2031 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2032 } else { |
| 2033 // Calling non-strict non-builtins with a value as the receiver |
| 2034 // requires boxing. |
| 2035 __ jmp(&miss); |
| 2365 } | 2036 } |
| 2366 break; | 2037 break; |
| 2367 | 2038 |
| 2368 case NUMBER_CHECK: { | 2039 case NUMBER_CHECK: |
| 2369 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2040 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
| 2370 // Calling non-strict non-builtins with a value as the receiver | |
| 2371 // requires boxing. | |
| 2372 __ jmp(&miss); | |
| 2373 } else { | |
| 2374 Label fast; | 2041 Label fast; |
| 2375 // Check that the object is a smi or a heap number. | 2042 // Check that the object is a smi or a heap number. |
| 2376 __ JumpIfSmi(rdx, &fast); | 2043 __ JumpIfSmi(rdx, &fast); |
| 2377 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); | 2044 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); |
| 2378 __ j(not_equal, &miss); | 2045 __ j(not_equal, &miss); |
| 2379 __ bind(&fast); | 2046 __ bind(&fast); |
| 2380 // Check that the maps starting from the prototype haven't changed. | 2047 // Check that the maps starting from the prototype haven't changed. |
| 2381 GenerateDirectLoadGlobalFunctionPrototype( | 2048 GenerateDirectLoadGlobalFunctionPrototype( |
| 2382 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); | 2049 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); |
| 2383 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2050 CheckPrototypes( |
| 2384 rbx, rdx, rdi, name, &miss); | 2051 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2385 } | 2052 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2386 break; | 2053 } else { |
| 2387 } | |
| 2388 | |
| 2389 case BOOLEAN_CHECK: { | |
| 2390 if (!function->IsBuiltin() && !function_info->strict_mode()) { | |
| 2391 // Calling non-strict non-builtins with a value as the receiver | 2054 // Calling non-strict non-builtins with a value as the receiver |
| 2392 // requires boxing. | 2055 // requires boxing. |
| 2393 __ jmp(&miss); | 2056 __ jmp(&miss); |
| 2394 } else { | 2057 } |
| 2058 break; |
| 2059 |
| 2060 case BOOLEAN_CHECK: |
| 2061 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
| 2395 Label fast; | 2062 Label fast; |
| 2396 // Check that the object is a boolean. | 2063 // Check that the object is a boolean. |
| 2397 __ CompareRoot(rdx, Heap::kTrueValueRootIndex); | 2064 __ CompareRoot(rdx, Heap::kTrueValueRootIndex); |
| 2398 __ j(equal, &fast); | 2065 __ j(equal, &fast); |
| 2399 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); | 2066 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); |
| 2400 __ j(not_equal, &miss); | 2067 __ j(not_equal, &miss); |
| 2401 __ bind(&fast); | 2068 __ bind(&fast); |
| 2402 // Check that the maps starting from the prototype haven't changed. | 2069 // Check that the maps starting from the prototype haven't changed. |
| 2403 GenerateDirectLoadGlobalFunctionPrototype( | 2070 GenerateDirectLoadGlobalFunctionPrototype( |
| 2404 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); | 2071 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); |
| 2405 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2072 CheckPrototypes( |
| 2406 rbx, rdx, rdi, name, &miss); | 2073 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2074 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2075 } else { |
| 2076 // Calling non-strict non-builtins with a value as the receiver |
| 2077 // requires boxing. |
| 2078 __ jmp(&miss); |
| 2407 } | 2079 } |
| 2408 break; | 2080 break; |
| 2409 } | |
| 2410 | |
| 2411 default: | |
| 2412 UNREACHABLE(); | |
| 2413 } | 2081 } |
| 2414 | 2082 |
| 2415 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2083 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2416 ? CALL_AS_FUNCTION | 2084 ? CALL_AS_FUNCTION |
| 2417 : CALL_AS_METHOD; | 2085 : CALL_AS_METHOD; |
| 2418 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2086 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2419 NullCallWrapper(), call_kind); | 2087 NullCallWrapper(), call_kind); |
| 2420 | 2088 |
| 2421 // Handle call cache miss. | 2089 // Handle call cache miss. |
| 2422 __ bind(&miss); | 2090 __ bind(&miss); |
| 2423 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2091 GenerateMissBranch(); |
| 2424 if (maybe_result->IsFailure()) return maybe_result; | |
| 2425 | 2092 |
| 2426 // Return the generated code. | 2093 // Return the generated code. |
| 2427 return TryGetCode(function); | 2094 return GetCode(function); |
| 2428 } | 2095 } |
| 2429 | 2096 |
| 2430 | 2097 |
| 2431 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2098 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2432 JSObject* holder, | 2099 Handle<JSObject> holder, |
| 2433 String* name) { | 2100 Handle<String> name) { |
| 2434 // ----------- S t a t e ------------- | 2101 // ----------- S t a t e ------------- |
| 2435 // rcx : function name | 2102 // rcx : function name |
| 2436 // rsp[0] : return address | 2103 // rsp[0] : return address |
| 2437 // rsp[8] : argument argc | 2104 // rsp[8] : argument argc |
| 2438 // rsp[16] : argument argc - 1 | 2105 // rsp[16] : argument argc - 1 |
| 2439 // ... | 2106 // ... |
| 2440 // rsp[argc * 8] : argument 1 | 2107 // rsp[argc * 8] : argument 1 |
| 2441 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2108 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2442 // ----------------------------------- | 2109 // ----------------------------------- |
| 2443 Label miss; | 2110 Label miss; |
| 2444 | 2111 GenerateNameCheck(name, &miss); |
| 2445 GenerateNameCheck(Handle<String>(name), &miss); | |
| 2446 | 2112 |
| 2447 // Get the number of arguments. | 2113 // Get the number of arguments. |
| 2448 const int argc = arguments().immediate(); | 2114 const int argc = arguments().immediate(); |
| 2449 | 2115 |
| 2450 LookupResult lookup(isolate()); | 2116 LookupResult lookup(isolate()); |
| 2451 LookupPostInterceptor(holder, name, &lookup); | 2117 LookupPostInterceptor(holder, name, &lookup); |
| 2452 | 2118 |
| 2453 // Get the receiver from the stack. | 2119 // Get the receiver from the stack. |
| 2454 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2120 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2455 | 2121 |
| 2456 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); | 2122 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); |
| 2457 MaybeObject* result = compiler.Compile(masm(), | 2123 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, |
| 2458 object, | 2124 &miss); |
| 2459 holder, | |
| 2460 name, | |
| 2461 &lookup, | |
| 2462 rdx, | |
| 2463 rbx, | |
| 2464 rdi, | |
| 2465 rax, | |
| 2466 &miss); | |
| 2467 if (result->IsFailure()) return result; | |
| 2468 | 2125 |
| 2469 // Restore receiver. | 2126 // Restore receiver. |
| 2470 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2127 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2471 | 2128 |
| 2472 // Check that the function really is a function. | 2129 // Check that the function really is a function. |
| 2473 __ JumpIfSmi(rax, &miss); | 2130 __ JumpIfSmi(rax, &miss); |
| 2474 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 2131 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 2475 __ j(not_equal, &miss); | 2132 __ j(not_equal, &miss); |
| 2476 | 2133 |
| 2477 // Patch the receiver on the stack with the global proxy if | 2134 // Patch the receiver on the stack with the global proxy if |
| 2478 // necessary. | 2135 // necessary. |
| 2479 if (object->IsGlobalObject()) { | 2136 if (object->IsGlobalObject()) { |
| 2480 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2137 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2481 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2138 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2482 } | 2139 } |
| 2483 | 2140 |
| 2484 // Invoke the function. | 2141 // Invoke the function. |
| 2485 __ movq(rdi, rax); | 2142 __ movq(rdi, rax); |
| 2486 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2143 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2487 ? CALL_AS_FUNCTION | 2144 ? CALL_AS_FUNCTION |
| 2488 : CALL_AS_METHOD; | 2145 : CALL_AS_METHOD; |
| 2489 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 2146 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2490 NullCallWrapper(), call_kind); | 2147 NullCallWrapper(), call_kind); |
| 2491 | 2148 |
| 2492 // Handle load cache miss. | 2149 // Handle load cache miss. |
| 2493 __ bind(&miss); | 2150 __ bind(&miss); |
| 2494 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2151 GenerateMissBranch(); |
| 2495 if (maybe_result->IsFailure()) return maybe_result; | |
| 2496 | 2152 |
| 2497 // Return the generated code. | 2153 // Return the generated code. |
| 2498 return TryGetCode(INTERCEPTOR, name); | 2154 return GetCode(INTERCEPTOR, name); |
| 2499 } | 2155 } |
| 2500 | 2156 |
| 2501 | 2157 |
| 2502 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, | 2158 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2503 GlobalObject* holder, | 2159 Handle<JSObject> object, |
| 2504 JSGlobalPropertyCell* cell, | 2160 Handle<GlobalObject> holder, |
| 2505 JSFunction* function, | 2161 Handle<JSGlobalPropertyCell> cell, |
| 2506 String* name) { | 2162 Handle<JSFunction> function, |
| 2163 Handle<String> name) { |
| 2507 // ----------- S t a t e ------------- | 2164 // ----------- S t a t e ------------- |
| 2508 // rcx : function name | 2165 // rcx : function name |
| 2509 // rsp[0] : return address | 2166 // rsp[0] : return address |
| 2510 // rsp[8] : argument argc | 2167 // rsp[8] : argument argc |
| 2511 // rsp[16] : argument argc - 1 | 2168 // rsp[16] : argument argc - 1 |
| 2512 // ... | 2169 // ... |
| 2513 // rsp[argc * 8] : argument 1 | 2170 // rsp[argc * 8] : argument 1 |
| 2514 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2171 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2515 // ----------------------------------- | 2172 // ----------------------------------- |
| 2516 | 2173 |
| 2517 if (HasCustomCallGenerator(function)) { | 2174 if (HasCustomCallGenerator(function)) { |
| 2518 MaybeObject* maybe_result = CompileCustomCall( | 2175 Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); |
| 2519 object, holder, cell, function, name); | 2176 // A null handle means bail out to the regular compiler code below. |
| 2520 Object* result; | 2177 if (!code.is_null()) return code; |
| 2521 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 2522 // undefined means bail out to regular compiler. | |
| 2523 if (!result->IsUndefined()) return result; | |
| 2524 } | 2178 } |
| 2525 | 2179 |
| 2526 Label miss; | 2180 Label miss; |
| 2527 | 2181 GenerateNameCheck(name, &miss); |
| 2528 GenerateNameCheck(Handle<String>(name), &miss); | |
| 2529 | 2182 |
| 2530 // Get the number of arguments. | 2183 // Get the number of arguments. |
| 2531 const int argc = arguments().immediate(); | 2184 const int argc = arguments().immediate(); |
| 2532 | |
| 2533 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2185 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2534 | |
| 2535 GenerateLoadFunctionFromCell(cell, function, &miss); | 2186 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2536 | 2187 |
| 2537 // Patch the receiver on the stack with the global proxy. | 2188 // Patch the receiver on the stack with the global proxy. |
| 2538 if (object->IsGlobalObject()) { | 2189 if (object->IsGlobalObject()) { |
| 2539 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2190 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2540 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2191 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2541 } | 2192 } |
| 2542 | 2193 |
| 2543 // Setup the context (function already in rdi). | 2194 // Setup the context (function already in rdi). |
| 2544 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2195 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2545 | 2196 |
| 2546 // Jump to the cached code (tail call). | 2197 // Jump to the cached code (tail call). |
| 2547 Counters* counters = isolate()->counters(); | 2198 Counters* counters = isolate()->counters(); |
| 2548 __ IncrementCounter(counters->call_global_inline(), 1); | 2199 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2549 ParameterCount expected(function->shared()->formal_parameter_count()); | 2200 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2550 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2201 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2551 ? CALL_AS_FUNCTION | 2202 ? CALL_AS_FUNCTION |
| 2552 : CALL_AS_METHOD; | 2203 : CALL_AS_METHOD; |
| 2553 // We call indirectly through the code field in the function to | 2204 // We call indirectly through the code field in the function to |
| 2554 // allow recompilation to take effect without changing any of the | 2205 // allow recompilation to take effect without changing any of the |
| 2555 // call sites. | 2206 // call sites. |
| 2556 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2207 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2557 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | 2208 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, |
| 2558 NullCallWrapper(), call_kind); | 2209 NullCallWrapper(), call_kind); |
| 2559 | 2210 |
| 2560 // Handle call cache miss. | 2211 // Handle call cache miss. |
| 2561 __ bind(&miss); | 2212 __ bind(&miss); |
| 2562 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2213 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2563 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2214 GenerateMissBranch(); |
| 2564 if (maybe_result->IsFailure()) return maybe_result; | |
| 2565 | 2215 |
| 2566 // Return the generated code. | 2216 // Return the generated code. |
| 2567 return TryGetCode(NORMAL, name); | 2217 return GetCode(NORMAL, name); |
| 2568 } | 2218 } |
| 2569 | 2219 |
| 2570 | 2220 |
| 2571 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 2221 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 2572 int index, | 2222 int index, |
| 2573 Handle<Map> transition, | 2223 Handle<Map> transition, |
| 2574 Handle<String> name) { | 2224 Handle<String> name) { |
| 2575 // ----------- S t a t e ------------- | 2225 // ----------- S t a t e ------------- |
| 2576 // -- rax : value | 2226 // -- rax : value |
| 2577 // -- rcx : name | 2227 // -- rcx : name |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 | 2552 |
| 2903 GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss); | 2553 GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss); |
| 2904 __ bind(&miss); | 2554 __ bind(&miss); |
| 2905 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2555 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2906 | 2556 |
| 2907 // Return the generated code. | 2557 // Return the generated code. |
| 2908 return GetCode(FIELD, name); | 2558 return GetCode(FIELD, name); |
| 2909 } | 2559 } |
| 2910 | 2560 |
| 2911 | 2561 |
| 2912 MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, | 2562 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 2913 JSObject* object, | 2563 Handle<String> name, |
| 2914 JSObject* holder, | 2564 Handle<JSObject> object, |
| 2915 AccessorInfo* callback) { | 2565 Handle<JSObject> holder, |
| 2566 Handle<AccessorInfo> callback) { |
| 2916 // ----------- S t a t e ------------- | 2567 // ----------- S t a t e ------------- |
| 2917 // -- rax : receiver | 2568 // -- rax : receiver |
| 2918 // -- rcx : name | 2569 // -- rcx : name |
| 2919 // -- rsp[0] : return address | 2570 // -- rsp[0] : return address |
| 2920 // ----------------------------------- | 2571 // ----------------------------------- |
| 2921 Label miss; | 2572 Label miss; |
| 2922 | 2573 GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi, callback, |
| 2923 MaybeObject* result = GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, | 2574 name, &miss); |
| 2924 rdi, callback, name, &miss); | |
| 2925 if (result->IsFailure()) { | |
| 2926 miss.Unuse(); | |
| 2927 return result; | |
| 2928 } | |
| 2929 | |
| 2930 __ bind(&miss); | 2575 __ bind(&miss); |
| 2931 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2576 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2932 | 2577 |
| 2933 // Return the generated code. | 2578 // Return the generated code. |
| 2934 return TryGetCode(CALLBACKS, name); | 2579 return GetCode(CALLBACKS, name); |
| 2935 } | 2580 } |
| 2936 | 2581 |
| 2937 | 2582 |
| 2938 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, | 2583 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
| 2939 Handle<JSObject> holder, | 2584 Handle<JSObject> holder, |
| 2940 Handle<Object> value, | 2585 Handle<Object> value, |
| 2941 Handle<String> name) { | 2586 Handle<String> name) { |
| 2942 // ----------- S t a t e ------------- | 2587 // ----------- S t a t e ------------- |
| 2943 // -- rax : receiver | 2588 // -- rax : receiver |
| 2944 // -- rcx : name | 2589 // -- rcx : name |
| 2945 // -- rsp[0] : return address | 2590 // -- rsp[0] : return address |
| 2946 // ----------------------------------- | 2591 // ----------------------------------- |
| 2947 Label miss; | 2592 Label miss; |
| 2948 | 2593 |
| 2949 GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss); | 2594 GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss); |
| 2950 __ bind(&miss); | 2595 __ bind(&miss); |
| 2951 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2596 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2952 | 2597 |
| 2953 // Return the generated code. | 2598 // Return the generated code. |
| 2954 return GetCode(CONSTANT_FUNCTION, name); | 2599 return GetCode(CONSTANT_FUNCTION, name); |
| 2955 } | 2600 } |
| 2956 | 2601 |
| 2957 | 2602 |
| 2958 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2603 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, |
| 2959 JSObject* holder, | 2604 Handle<JSObject> holder, |
| 2960 String* name) { | 2605 Handle<String> name) { |
| 2961 // ----------- S t a t e ------------- | 2606 // ----------- S t a t e ------------- |
| 2962 // -- rax : receiver | 2607 // -- rax : receiver |
| 2963 // -- rcx : name | 2608 // -- rcx : name |
| 2964 // -- rsp[0] : return address | 2609 // -- rsp[0] : return address |
| 2965 // ----------------------------------- | 2610 // ----------------------------------- |
| 2966 Label miss; | 2611 Label miss; |
| 2967 | |
| 2968 LookupResult lookup(isolate()); | 2612 LookupResult lookup(isolate()); |
| 2969 LookupPostInterceptor(holder, name, &lookup); | 2613 LookupPostInterceptor(holder, name, &lookup); |
| 2970 | 2614 |
| 2971 // TODO(368): Compile in the whole chain: all the interceptors in | 2615 // TODO(368): Compile in the whole chain: all the interceptors in |
| 2972 // prototypes and ultimate answer. | 2616 // prototypes and ultimate answer. |
| 2973 GenerateLoadInterceptor(receiver, | 2617 GenerateLoadInterceptor(receiver, holder, &lookup, rax, rcx, rdx, rbx, rdi, |
| 2974 holder, | 2618 name, &miss); |
| 2975 &lookup, | |
| 2976 rax, | |
| 2977 rcx, | |
| 2978 rdx, | |
| 2979 rbx, | |
| 2980 rdi, | |
| 2981 name, | |
| 2982 &miss); | |
| 2983 | |
| 2984 __ bind(&miss); | 2619 __ bind(&miss); |
| 2985 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2620 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2986 | 2621 |
| 2987 // Return the generated code. | 2622 // Return the generated code. |
| 2988 return TryGetCode(INTERCEPTOR, name); | 2623 return GetCode(INTERCEPTOR, name); |
| 2989 } | 2624 } |
| 2990 | 2625 |
| 2991 | 2626 |
| 2992 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2627 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 2993 Handle<JSObject> object, | 2628 Handle<JSObject> object, |
| 2994 Handle<GlobalObject> holder, | 2629 Handle<GlobalObject> holder, |
| 2995 Handle<JSGlobalPropertyCell> cell, | 2630 Handle<JSGlobalPropertyCell> cell, |
| 2996 Handle<String> name, | 2631 Handle<String> name, |
| 2997 bool is_dont_delete) { | 2632 bool is_dont_delete) { |
| 2998 // ----------- S t a t e ------------- | 2633 // ----------- S t a t e ------------- |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3061 | 2696 |
| 3062 __ bind(&miss); | 2697 __ bind(&miss); |
| 3063 __ DecrementCounter(counters->keyed_load_field(), 1); | 2698 __ DecrementCounter(counters->keyed_load_field(), 1); |
| 3064 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2699 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3065 | 2700 |
| 3066 // Return the generated code. | 2701 // Return the generated code. |
| 3067 return GetCode(FIELD, name); | 2702 return GetCode(FIELD, name); |
| 3068 } | 2703 } |
| 3069 | 2704 |
| 3070 | 2705 |
| 3071 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2706 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
| 3072 String* name, | 2707 Handle<String> name, |
| 3073 JSObject* receiver, | 2708 Handle<JSObject> receiver, |
| 3074 JSObject* holder, | 2709 Handle<JSObject> holder, |
| 3075 AccessorInfo* callback) { | 2710 Handle<AccessorInfo> callback) { |
| 3076 // ----------- S t a t e ------------- | 2711 // ----------- S t a t e ------------- |
| 3077 // -- rax : key | 2712 // -- rax : key |
| 3078 // -- rdx : receiver | 2713 // -- rdx : receiver |
| 3079 // -- rsp[0] : return address | 2714 // -- rsp[0] : return address |
| 3080 // ----------------------------------- | 2715 // ----------------------------------- |
| 3081 Label miss; | 2716 Label miss; |
| 3082 | |
| 3083 Counters* counters = isolate()->counters(); | 2717 Counters* counters = isolate()->counters(); |
| 3084 __ IncrementCounter(counters->keyed_load_callback(), 1); | 2718 __ IncrementCounter(counters->keyed_load_callback(), 1); |
| 3085 | 2719 |
| 3086 // Check that the name has not changed. | 2720 // Check that the name has not changed. |
| 3087 __ Cmp(rax, Handle<String>(name)); | 2721 __ Cmp(rax, name); |
| 3088 __ j(not_equal, &miss); | 2722 __ j(not_equal, &miss); |
| 3089 | 2723 |
| 3090 MaybeObject* result = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, | 2724 GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi, callback, |
| 3091 rcx, rdi, callback, name, &miss); | 2725 name, &miss); |
| 3092 if (result->IsFailure()) { | |
| 3093 miss.Unuse(); | |
| 3094 return result; | |
| 3095 } | |
| 3096 | |
| 3097 __ bind(&miss); | 2726 __ bind(&miss); |
| 3098 | |
| 3099 __ DecrementCounter(counters->keyed_load_callback(), 1); | 2727 __ DecrementCounter(counters->keyed_load_callback(), 1); |
| 3100 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2728 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3101 | 2729 |
| 3102 // Return the generated code. | 2730 // Return the generated code. |
| 3103 return TryGetCode(CALLBACKS, name); | 2731 return GetCode(CALLBACKS, name); |
| 3104 } | 2732 } |
| 3105 | 2733 |
| 3106 | 2734 |
| 3107 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( | 2735 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
| 3108 Handle<String> name, | 2736 Handle<String> name, |
| 3109 Handle<JSObject> receiver, | 2737 Handle<JSObject> receiver, |
| 3110 Handle<JSObject> holder, | 2738 Handle<JSObject> holder, |
| 3111 Handle<Object> value) { | 2739 Handle<Object> value) { |
| 3112 // ----------- S t a t e ------------- | 2740 // ----------- S t a t e ------------- |
| 3113 // -- rax : key | 2741 // -- rax : key |
| 3114 // -- rdx : receiver | 2742 // -- rdx : receiver |
| 3115 // -- rsp[0] : return address | 2743 // -- rsp[0] : return address |
| 3116 // ----------------------------------- | 2744 // ----------------------------------- |
| 3117 Label miss; | 2745 Label miss; |
| 3118 | 2746 |
| 3119 Counters* counters = isolate()->counters(); | 2747 Counters* counters = isolate()->counters(); |
| 3120 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 2748 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
| 3121 | 2749 |
| 3122 // Check that the name has not changed. | 2750 // Check that the name has not changed. |
| 3123 __ Cmp(rax, Handle<String>(name)); | 2751 __ Cmp(rax, name); |
| 3124 __ j(not_equal, &miss); | 2752 __ j(not_equal, &miss); |
| 3125 | 2753 |
| 3126 GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi, | 2754 GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi, |
| 3127 value, name, &miss); | 2755 value, name, &miss); |
| 3128 __ bind(&miss); | 2756 __ bind(&miss); |
| 3129 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 2757 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
| 3130 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2758 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3131 | 2759 |
| 3132 // Return the generated code. | 2760 // Return the generated code. |
| 3133 return GetCode(CONSTANT_FUNCTION, name); | 2761 return GetCode(CONSTANT_FUNCTION, name); |
| 3134 } | 2762 } |
| 3135 | 2763 |
| 3136 | 2764 |
| 3137 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2765 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
| 3138 JSObject* holder, | 2766 Handle<JSObject> receiver, |
| 3139 String* name) { | 2767 Handle<JSObject> holder, |
| 2768 Handle<String> name) { |
| 3140 // ----------- S t a t e ------------- | 2769 // ----------- S t a t e ------------- |
| 3141 // -- rax : key | 2770 // -- rax : key |
| 3142 // -- rdx : receiver | 2771 // -- rdx : receiver |
| 3143 // -- rsp[0] : return address | 2772 // -- rsp[0] : return address |
| 3144 // ----------------------------------- | 2773 // ----------------------------------- |
| 3145 Label miss; | 2774 Label miss; |
| 3146 | |
| 3147 Counters* counters = isolate()->counters(); | 2775 Counters* counters = isolate()->counters(); |
| 3148 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 2776 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
| 3149 | 2777 |
| 3150 // Check that the name has not changed. | 2778 // Check that the name has not changed. |
| 3151 __ Cmp(rax, Handle<String>(name)); | 2779 __ Cmp(rax, name); |
| 3152 __ j(not_equal, &miss); | 2780 __ j(not_equal, &miss); |
| 3153 | 2781 |
| 3154 LookupResult lookup(isolate()); | 2782 LookupResult lookup(isolate()); |
| 3155 LookupPostInterceptor(holder, name, &lookup); | 2783 LookupPostInterceptor(holder, name, &lookup); |
| 3156 GenerateLoadInterceptor(receiver, | 2784 GenerateLoadInterceptor(receiver, holder, &lookup, rdx, rax, rcx, rbx, rdi, |
| 3157 holder, | 2785 name, &miss); |
| 3158 &lookup, | |
| 3159 rdx, | |
| 3160 rax, | |
| 3161 rcx, | |
| 3162 rbx, | |
| 3163 rdi, | |
| 3164 name, | |
| 3165 &miss); | |
| 3166 __ bind(&miss); | 2786 __ bind(&miss); |
| 3167 __ DecrementCounter(counters->keyed_load_interceptor(), 1); | 2787 __ DecrementCounter(counters->keyed_load_interceptor(), 1); |
| 3168 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2788 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3169 | 2789 |
| 3170 // Return the generated code. | 2790 // Return the generated code. |
| 3171 return TryGetCode(INTERCEPTOR, name); | 2791 return GetCode(INTERCEPTOR, name); |
| 3172 } | 2792 } |
| 3173 | 2793 |
| 3174 | 2794 |
| 3175 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( | 2795 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
| 3176 Handle<String> name) { | 2796 Handle<String> name) { |
| 3177 // ----------- S t a t e ------------- | 2797 // ----------- S t a t e ------------- |
| 3178 // -- rax : key | 2798 // -- rax : key |
| 3179 // -- rdx : receiver | 2799 // -- rdx : receiver |
| 3180 // -- rsp[0] : return address | 2800 // -- rsp[0] : return address |
| 3181 // ----------------------------------- | 2801 // ----------------------------------- |
| (...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4003 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3623 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4004 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 3624 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
| 4005 } | 3625 } |
| 4006 | 3626 |
| 4007 | 3627 |
| 4008 #undef __ | 3628 #undef __ |
| 4009 | 3629 |
| 4010 } } // namespace v8::internal | 3630 } } // namespace v8::internal |
| 4011 | 3631 |
| 4012 #endif // V8_TARGET_ARCH_X64 | 3632 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |