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 |