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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 8391045: Handlify the remaining CallStubCompiler functions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/arm/stub-cache-arm.cc ('K') | « src/x64/macro-assembler-x64.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 &regular_invoke); 560 &regular_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(&regular_invoke); 599 __ bind(&regular_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
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
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
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
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
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
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
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
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
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, &not_smi); 1844 __ JumpIfNotSmi(rax, &not_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
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
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
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
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
OLDNEW
« src/arm/stub-cache-arm.cc ('K') | « src/x64/macro-assembler-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698