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

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

Powered by Google App Engine
This is Rietveld 408576698