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

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

Issue 660095: Merge revision 3813 to 3930 from bleeding_edge to partial snapshots branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: '' Created 10 years, 10 months 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
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ia32/virtual-frame-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 145
146 // Probe the secondary table. 146 // Probe the secondary table.
147 ProbeTable(masm, flags, kSecondary, name, scratch, extra); 147 ProbeTable(masm, flags, kSecondary, name, scratch, extra);
148 148
149 // Cache miss: Fall-through and let caller handle the miss by 149 // Cache miss: Fall-through and let caller handle the miss by
150 // entering the runtime system. 150 // entering the runtime system.
151 __ bind(&miss); 151 __ bind(&miss);
152 } 152 }
153 153
154 154
155 static void PushInterceptorArguments(MacroAssembler* masm,
156 Register receiver,
157 Register holder,
158 Register name,
159 JSObject* holder_obj) {
160 __ push(receiver);
161 __ push(holder);
162 __ push(name);
163 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
164 ASSERT(!Heap::InNewSpace(interceptor));
165 __ mov(receiver, Immediate(Handle<Object>(interceptor)));
166 __ push(receiver);
167 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset));
168 }
169
170
171 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 155 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
172 int index, 156 int index,
173 Register prototype) { 157 Register prototype) {
174 // Load the global or builtins object from the current context. 158 // Load the global or builtins object from the current context.
175 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); 159 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
176 // Load the global context from the global or builtins object. 160 // Load the global context from the global or builtins object.
177 __ mov(prototype, 161 __ mov(prototype,
178 FieldOperand(prototype, GlobalObject::kGlobalContextOffset)); 162 FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
179 // Load the function from the global context. 163 // Load the function from the global context.
180 __ mov(prototype, Operand(prototype, Context::SlotOffset(index))); 164 __ mov(prototype, Operand(prototype, Context::SlotOffset(index)));
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 203 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
220 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 204 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
221 ASSERT(kNotStringTag != 0); 205 ASSERT(kNotStringTag != 0);
222 __ test(scratch, Immediate(kNotStringTag)); 206 __ test(scratch, Immediate(kNotStringTag));
223 __ j(not_zero, non_string_object, not_taken); 207 __ j(not_zero, non_string_object, not_taken);
224 } 208 }
225 209
226 210
227 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 211 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
228 Register receiver, 212 Register receiver,
229 Register scratch, 213 Register scratch1,
214 Register scratch2,
230 Label* miss) { 215 Label* miss) {
231 Label load_length, check_wrapper; 216 Label check_wrapper;
232 217
233 // Check if the object is a string leaving the instance type in the 218 // Check if the object is a string leaving the instance type in the
234 // scratch register. 219 // scratch register.
235 GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper); 220 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper);
236 221
237 // Load length from the string and convert to a smi. 222 // Load length from the string and convert to a smi.
238 __ bind(&load_length);
239 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); 223 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
240 __ SmiTag(eax); 224 __ SmiTag(eax);
241 __ ret(0); 225 __ ret(0);
242 226
243 // Check if the object is a JSValue wrapper. 227 // Check if the object is a JSValue wrapper.
244 __ bind(&check_wrapper); 228 __ bind(&check_wrapper);
245 __ cmp(scratch, JS_VALUE_TYPE); 229 __ cmp(scratch1, JS_VALUE_TYPE);
246 __ j(not_equal, miss, not_taken); 230 __ j(not_equal, miss, not_taken);
247 231
248 // Check if the wrapped value is a string and load the length 232 // Check if the wrapped value is a string and load the length
249 // directly if it is. 233 // directly if it is.
250 __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset)); 234 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
251 GenerateStringCheck(masm, receiver, scratch, miss, miss); 235 GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
252 __ jmp(&load_length); 236 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
237 __ SmiTag(eax);
238 __ ret(0);
253 } 239 }
254 240
255 241
256 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 242 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
257 Register receiver, 243 Register receiver,
258 Register scratch1, 244 Register scratch1,
259 Register scratch2, 245 Register scratch2,
260 Label* miss_label) { 246 Label* miss_label) {
261 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 247 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
262 __ mov(eax, Operand(scratch1)); 248 __ mov(eax, Operand(scratch1));
(...skipping 15 matching lines...) Expand all
278 __ mov(dst, FieldOperand(src, offset)); 264 __ mov(dst, FieldOperand(src, offset));
279 } else { 265 } else {
280 // Calculate the offset into the properties array. 266 // Calculate the offset into the properties array.
281 int offset = index * kPointerSize + FixedArray::kHeaderSize; 267 int offset = index * kPointerSize + FixedArray::kHeaderSize;
282 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); 268 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
283 __ mov(dst, FieldOperand(dst, offset)); 269 __ mov(dst, FieldOperand(dst, offset));
284 } 270 }
285 } 271 }
286 272
287 273
274 static void PushInterceptorArguments(MacroAssembler* masm,
275 Register receiver,
276 Register holder,
277 Register name,
278 JSObject* holder_obj) {
279 __ push(receiver);
280 __ push(holder);
281 __ push(name);
282 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
283 ASSERT(!Heap::InNewSpace(interceptor));
284 __ mov(receiver, Immediate(Handle<Object>(interceptor)));
285 __ push(receiver);
286 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset));
287 }
288
289
288 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, 290 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
289 Register receiver, 291 Register receiver,
290 Register holder, 292 Register holder,
291 Register name, 293 Register name,
292 JSObject* holder_obj) { 294 JSObject* holder_obj) {
293 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 295 PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
294 296 __ CallExternalReference(
295 ExternalReference ref = 297 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)),
296 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); 298 5);
297 __ mov(eax, Immediate(5));
298 __ mov(ebx, Immediate(ref));
299
300 CEntryStub stub(1);
301 __ CallStub(&stub);
302 } 299 }
303 300
304 301
305 template <class Compiler> 302 template <class Compiler>
306 static void CompileLoadInterceptor(Compiler* compiler, 303 static void CompileLoadInterceptor(Compiler* compiler,
307 StubCompiler* stub_compiler, 304 StubCompiler* stub_compiler,
308 MacroAssembler* masm, 305 MacroAssembler* masm,
309 JSObject* object, 306 JSObject* object,
310 JSObject* holder, 307 JSObject* holder,
311 String* name, 308 String* name,
312 LookupResult* lookup, 309 LookupResult* lookup,
313 Register receiver, 310 Register receiver,
314 Register scratch1, 311 Register scratch1,
315 Register scratch2, 312 Register scratch2,
316 Label* miss) { 313 Label* miss) {
317 ASSERT(holder->HasNamedInterceptor()); 314 ASSERT(holder->HasNamedInterceptor());
318 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 315 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
319 316
320 // Check that the receiver isn't a smi. 317 // Check that the receiver isn't a smi.
321 __ test(receiver, Immediate(kSmiTagMask)); 318 __ test(receiver, Immediate(kSmiTagMask));
322 __ j(zero, miss, not_taken); 319 __ j(zero, miss, not_taken);
323 320
324 // Check that the maps haven't changed. 321 // Check that the maps haven't changed.
325 Register reg = 322 Register reg =
326 stub_compiler->CheckPrototypes(object, receiver, holder, 323 stub_compiler->CheckPrototypes(object, receiver, holder,
327 scratch1, scratch2, name, miss); 324 scratch1, scratch2, name, miss);
328 325
329 if (lookup->IsValid() && lookup->IsCacheable()) { 326 if (lookup->IsProperty() && lookup->IsCacheable()) {
330 compiler->CompileCacheable(masm, 327 compiler->CompileCacheable(masm,
331 stub_compiler, 328 stub_compiler,
332 receiver, 329 receiver,
333 reg, 330 reg,
334 scratch1, 331 scratch1,
335 scratch2, 332 scratch2,
336 holder, 333 holder,
337 lookup, 334 lookup,
338 name, 335 name,
339 miss); 336 miss);
(...skipping 15 matching lines...) Expand all
355 void CompileCacheable(MacroAssembler* masm, 352 void CompileCacheable(MacroAssembler* masm,
356 StubCompiler* stub_compiler, 353 StubCompiler* stub_compiler,
357 Register receiver, 354 Register receiver,
358 Register holder, 355 Register holder,
359 Register scratch1, 356 Register scratch1,
360 Register scratch2, 357 Register scratch2,
361 JSObject* holder_obj, 358 JSObject* holder_obj,
362 LookupResult* lookup, 359 LookupResult* lookup,
363 String* name, 360 String* name,
364 Label* miss_label) { 361 Label* miss_label) {
365 AccessorInfo* callback = 0; 362 AccessorInfo* callback = NULL;
366 bool optimize = false; 363 bool optimize = false;
367 // So far the most popular follow ups for interceptor loads are FIELD 364 // So far the most popular follow ups for interceptor loads are FIELD
368 // and CALLBACKS, so inline only them, other cases may be added 365 // and CALLBACKS, so inline only them, other cases may be added
369 // later. 366 // later.
370 if (lookup->type() == FIELD) { 367 if (lookup->type() == FIELD) {
371 optimize = true; 368 optimize = true;
372 } else if (lookup->type() == CALLBACKS) { 369 } else if (lookup->type() == CALLBACKS) {
373 Object* callback_object = lookup->GetCallbackObject(); 370 Object* callback_object = lookup->GetCallbackObject();
374 if (callback_object->IsAccessorInfo()) { 371 if (callback_object->IsAccessorInfo()) {
375 callback = AccessorInfo::cast(callback_object); 372 callback = AccessorInfo::cast(callback_object);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 ExternalReference ref = ExternalReference( 469 ExternalReference ref = ExternalReference(
473 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 470 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
474 __ TailCallRuntime(ref, 5, 1); 471 __ TailCallRuntime(ref, 5, 1);
475 } 472 }
476 473
477 private: 474 private:
478 Register name_; 475 Register name_;
479 }; 476 };
480 477
481 478
479 // Holds information about possible function call optimizations.
480 class CallOptimization BASE_EMBEDDED {
481 public:
482 explicit CallOptimization(LookupResult* lookup)
483 : constant_function_(NULL),
484 is_simple_api_call_(false),
485 expected_receiver_type_(NULL),
486 api_call_info_(NULL) {
487 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
488
489 // We only optimize constant function calls.
490 if (lookup->type() != CONSTANT_FUNCTION) return;
491
492 Initialize(lookup->GetConstantFunction());
493 }
494
495 explicit CallOptimization(JSFunction* function) {
496 Initialize(function);
497 }
498
499 bool is_constant_call() const {
500 return constant_function_ != NULL;
501 }
502
503 JSFunction* constant_function() const {
504 ASSERT(constant_function_ != NULL);
505 return constant_function_;
506 }
507
508 bool is_simple_api_call() const {
509 return is_simple_api_call_;
510 }
511
512 FunctionTemplateInfo* expected_receiver_type() const {
513 ASSERT(is_simple_api_call_);
514 return expected_receiver_type_;
515 }
516
517 CallHandlerInfo* api_call_info() const {
518 ASSERT(is_simple_api_call_);
519 return api_call_info_;
520 }
521
522 // Returns the depth of the object having the expected type in the
523 // prototype chain between the two arguments.
524 int GetPrototypeDepthOfExpectedType(JSObject* object,
525 JSObject* holder) const {
526 ASSERT(is_simple_api_call_);
527 if (expected_receiver_type_ == NULL) return 0;
528 int depth = 0;
529 while (object != holder) {
530 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
531 object = JSObject::cast(object->GetPrototype());
532 ++depth;
533 }
534 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
535 return kInvalidProtoDepth;
536 }
537
538 private:
539 void Initialize(JSFunction* function) {
540 if (!function->is_compiled()) return;
541
542 constant_function_ = function;
543 is_simple_api_call_ = false;
544
545 AnalyzePossibleApiFunction(function);
546 }
547
548 // Determines whether the given function can be called using the
549 // fast api call builtin.
550 void AnalyzePossibleApiFunction(JSFunction* function) {
551 SharedFunctionInfo* sfi = function->shared();
552 if (sfi->function_data()->IsUndefined()) return;
553 FunctionTemplateInfo* info =
554 FunctionTemplateInfo::cast(sfi->function_data());
555
556 // Require a C++ callback.
557 if (info->call_code()->IsUndefined()) return;
558 api_call_info_ = CallHandlerInfo::cast(info->call_code());
559
560 // Accept signatures that either have no restrictions at all or
561 // only have restrictions on the receiver.
562 if (!info->signature()->IsUndefined()) {
563 SignatureInfo* signature = SignatureInfo::cast(info->signature());
564 if (!signature->args()->IsUndefined()) return;
565 if (!signature->receiver()->IsUndefined()) {
566 expected_receiver_type_ =
567 FunctionTemplateInfo::cast(signature->receiver());
568 }
569 }
570
571 is_simple_api_call_ = true;
572 }
573
574 JSFunction* constant_function_;
575 bool is_simple_api_call_;
576 FunctionTemplateInfo* expected_receiver_type_;
577 CallHandlerInfo* api_call_info_;
578 };
579
580
581 // Reserves space for the extra arguments to FastHandleApiCall in the
582 // caller's frame.
583 //
584 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
585 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
586 // ----------- S t a t e -------------
587 // -- esp[0] : return address
588 // -- esp[4] : last argument in the internal frame of the caller
589 // -----------------------------------
590 __ pop(scratch);
591 __ push(Immediate(Smi::FromInt(0)));
592 __ push(Immediate(Smi::FromInt(0)));
593 __ push(Immediate(Smi::FromInt(0)));
594 __ push(Immediate(Smi::FromInt(0)));
595 __ push(scratch);
596 }
597
598
599 // Undoes the effects of ReserveSpaceForFastApiCall.
600 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
601 // ----------- S t a t e -------------
602 // -- esp[0] : return address
603 // -- esp[4] : last fast api call extra argument
604 // -- ...
605 // -- esp[16] : first fast api call extra argument
606 // -- esp[20] : last argument in the internal frame
607 // -----------------------------------
608 __ pop(scratch);
609 __ add(Operand(esp), Immediate(kPointerSize * 4));
610 __ push(scratch);
611 }
612
613
614 // Generates call to FastHandleApiCall builtin.
615 static void GenerateFastApiCall(MacroAssembler* masm,
616 const CallOptimization& optimization,
617 int argc) {
618 // ----------- S t a t e -------------
619 // -- esp[0] : return address
620 // -- esp[4] : object passing the type check
621 // (last fast api call extra argument,
622 // set by CheckPrototypes)
623 // -- esp[8] : api call data
624 // -- esp[12] : api callback
625 // -- esp[16] : api function
626 // (first fast api call extra argument)
627 // -- esp[20] : last argument
628 // -- ...
629 // -- esp[(argc + 5) * 4] : first argument
630 // -- esp[(argc + 6) * 4] : receiver
631 // -----------------------------------
632
633 // Get the function and setup the context.
634 JSFunction* function = optimization.constant_function();
635 __ mov(edi, Immediate(Handle<JSFunction>(function)));
636 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
637
638 // Pass the additional arguments FastHandleApiCall expects.
639 __ mov(Operand(esp, 4 * kPointerSize), edi);
640 bool info_loaded = false;
641 Object* callback = optimization.api_call_info()->callback();
642 if (Heap::InNewSpace(callback)) {
643 info_loaded = true;
644 __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info()));
645 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kCallbackOffset));
646 __ mov(Operand(esp, 3 * kPointerSize), ebx);
647 } else {
648 __ mov(Operand(esp, 3 * kPointerSize), Immediate(Handle<Object>(callback)));
649 }
650 Object* call_data = optimization.api_call_info()->data();
651 if (Heap::InNewSpace(call_data)) {
652 if (!info_loaded) {
653 __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info()));
654 }
655 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset));
656 __ mov(Operand(esp, 2 * kPointerSize), ebx);
657 } else {
658 __ mov(Operand(esp, 2 * kPointerSize),
659 Immediate(Handle<Object>(call_data)));
660 }
661
662 // Set the number of arguments.
663 __ mov(eax, Immediate(argc + 4));
664
665 // Jump to the fast api call builtin (tail call).
666 Handle<Code> code = Handle<Code>(
667 Builtins::builtin(Builtins::FastHandleApiCall));
668 ParameterCount expected(0);
669 __ InvokeCode(code, expected, expected,
670 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
671 }
672
673
482 class CallInterceptorCompiler BASE_EMBEDDED { 674 class CallInterceptorCompiler BASE_EMBEDDED {
483 public: 675 public:
484 CallInterceptorCompiler(const ParameterCount& arguments, Register name) 676 CallInterceptorCompiler(StubCompiler* stub_compiler,
485 : arguments_(arguments), argc_(arguments.immediate()), name_(name) {} 677 const ParameterCount& arguments,
486 678 Register name)
679 : stub_compiler_(stub_compiler),
680 arguments_(arguments),
681 name_(name) {}
682
683 void Compile(MacroAssembler* masm,
684 JSObject* object,
685 JSObject* holder,
686 String* name,
687 LookupResult* lookup,
688 Register receiver,
689 Register scratch1,
690 Register scratch2,
691 Label* miss) {
692 ASSERT(holder->HasNamedInterceptor());
693 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
694
695 // Check that the receiver isn't a smi.
696 __ test(receiver, Immediate(kSmiTagMask));
697 __ j(zero, miss, not_taken);
698
699 CallOptimization optimization(lookup);
700
701 if (optimization.is_constant_call() &&
702 !Top::CanHaveSpecialFunctions(holder)) {
703 CompileCacheable(masm,
704 object,
705 receiver,
706 scratch1,
707 scratch2,
708 holder,
709 lookup,
710 name,
711 optimization,
712 miss);
713 } else {
714 CompileRegular(masm,
715 object,
716 receiver,
717 scratch1,
718 scratch2,
719 name,
720 holder,
721 miss);
722 }
723 }
724
725 private:
487 void CompileCacheable(MacroAssembler* masm, 726 void CompileCacheable(MacroAssembler* masm,
488 StubCompiler* stub_compiler, 727 JSObject* object,
489 Register receiver, 728 Register receiver,
490 Register holder,
491 Register scratch1, 729 Register scratch1,
492 Register scratch2, 730 Register scratch2,
493 JSObject* holder_obj, 731 JSObject* holder_obj,
494 LookupResult* lookup, 732 LookupResult* lookup,
495 String* name, 733 String* name,
734 const CallOptimization& optimization,
496 Label* miss_label) { 735 Label* miss_label) {
497 JSFunction* function = 0; 736 ASSERT(optimization.is_constant_call());
498 bool optimize = false; 737 ASSERT(!lookup->holder()->IsGlobalObject());
499 // So far the most popular case for failed interceptor is 738
500 // CONSTANT_FUNCTION sitting below. 739 int depth1 = kInvalidProtoDepth;
501 if (lookup->type() == CONSTANT_FUNCTION) { 740 int depth2 = kInvalidProtoDepth;
502 function = lookup->GetConstantFunction(); 741 bool can_do_fast_api_call = false;
503 // JSArray holder is a special case for call constant function 742 if (optimization.is_simple_api_call() &&
504 // (see the corresponding code). 743 !lookup->holder()->IsGlobalObject()) {
505 if (function->is_compiled() && !holder_obj->IsJSArray()) { 744 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj);
506 optimize = true; 745 if (depth1 == kInvalidProtoDepth) {
746 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj,
747 lookup->holder());
507 } 748 }
508 } 749 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
509 750 (depth2 != kInvalidProtoDepth);
510 if (!optimize) { 751 }
511 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); 752
512 return; 753 __ IncrementCounter(&Counters::call_const_interceptor, 1);
513 } 754
514 755 if (can_do_fast_api_call) {
515 __ EnterInternalFrame(); 756 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1);
516 __ push(holder); // Save the holder. 757 ReserveSpaceForFastApiCall(masm, scratch1);
517 __ push(name_); // Save the name. 758 }
518 759
519 CompileCallLoadPropertyWithInterceptor(masm, 760 Label miss_cleanup;
520 receiver, 761 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
521 holder, 762 Register holder =
522 name_, 763 stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
523 holder_obj); 764 scratch1, scratch2, name,
524 765 depth1, miss);
525 __ pop(name_); // Restore the name. 766
526 __ pop(receiver); // Restore the holder. 767 Label regular_invoke;
527 __ LeaveInternalFrame(); 768 LoadWithInterceptor(masm, receiver, holder, holder_obj, &regular_invoke);
528 769
529 __ cmp(eax, Factory::no_interceptor_result_sentinel()); 770 // Generate code for the failed interceptor case.
530 Label invoke; 771
531 __ j(not_equal, &invoke); 772 // Check the lookup is still valid.
532 773 stub_compiler_->CheckPrototypes(holder_obj, receiver,
533 stub_compiler->CheckPrototypes(holder_obj, receiver, 774 lookup->holder(),
534 lookup->holder(), scratch1, 775 scratch1, scratch2, name,
535 scratch2, 776 depth2, miss);
536 name, 777
537 miss_label); 778 if (can_do_fast_api_call) {
538 if (lookup->holder()->IsGlobalObject()) { 779 GenerateFastApiCall(masm, optimization, arguments_.immediate());
539 __ mov(edx, Operand(esp, (argc_ + 1) * kPointerSize)); 780 } else {
540 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 781 __ InvokeFunction(optimization.constant_function(), arguments_,
541 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edx); 782 JUMP_FUNCTION);
542 } 783 }
543 784
544 ASSERT(function->is_compiled()); 785 if (can_do_fast_api_call) {
545 // Get the function and setup the context. 786 __ bind(&miss_cleanup);
546 __ mov(edi, Immediate(Handle<JSFunction>(function))); 787 FreeSpaceForFastApiCall(masm, scratch1);
547 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 788 __ jmp(miss_label);
548 789 }
549 // Jump to the cached code (tail call). 790
550 Handle<Code> code(function->code()); 791 __ bind(&regular_invoke);
551 ParameterCount expected(function->shared()->formal_parameter_count()); 792 if (can_do_fast_api_call) {
552 __ InvokeCode(code, expected, arguments_, 793 FreeSpaceForFastApiCall(masm, scratch1);
553 RelocInfo::CODE_TARGET, JUMP_FUNCTION); 794 }
554
555 __ bind(&invoke);
556 } 795 }
557 796
558 void CompileRegular(MacroAssembler* masm, 797 void CompileRegular(MacroAssembler* masm,
798 JSObject* object,
559 Register receiver, 799 Register receiver,
560 Register holder, 800 Register scratch1,
561 Register scratch, 801 Register scratch2,
802 String* name,
562 JSObject* holder_obj, 803 JSObject* holder_obj,
563 Label* miss_label) { 804 Label* miss_label) {
805 Register holder =
806 stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
807 scratch1, scratch2, name,
808 miss_label);
809
564 __ EnterInternalFrame(); 810 __ EnterInternalFrame();
565 // Save the name_ register across the call. 811 // Save the name_ register across the call.
566 __ push(name_); 812 __ push(name_);
567 813
568 PushInterceptorArguments(masm, 814 PushInterceptorArguments(masm,
569 receiver, 815 receiver,
570 holder, 816 holder,
571 name_, 817 name_,
572 holder_obj); 818 holder_obj);
573 819
574 ExternalReference ref = ExternalReference( 820 __ CallExternalReference(
575 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); 821 ExternalReference(
576 __ mov(eax, Immediate(5)); 822 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
577 __ mov(ebx, Immediate(ref)); 823 5);
578
579 CEntryStub stub(1);
580 __ CallStub(&stub);
581 824
582 // Restore the name_ register. 825 // Restore the name_ register.
583 __ pop(name_); 826 __ pop(name_);
584 __ LeaveInternalFrame(); 827 __ LeaveInternalFrame();
585 } 828 }
586 829
587 private: 830 void LoadWithInterceptor(MacroAssembler* masm,
831 Register receiver,
832 Register holder,
833 JSObject* holder_obj,
834 Label* interceptor_succeeded) {
835 __ EnterInternalFrame();
836 __ push(holder); // Save the holder.
837 __ push(name_); // Save the name.
838
839 CompileCallLoadPropertyWithInterceptor(masm,
840 receiver,
841 holder,
842 name_,
843 holder_obj);
844
845 __ pop(name_); // Restore the name.
846 __ pop(receiver); // Restore the holder.
847 __ LeaveInternalFrame();
848
849 __ cmp(eax, Factory::no_interceptor_result_sentinel());
850 __ j(not_equal, interceptor_succeeded);
851 }
852
853 StubCompiler* stub_compiler_;
588 const ParameterCount& arguments_; 854 const ParameterCount& arguments_;
589 int argc_;
590 Register name_; 855 Register name_;
591 }; 856 };
592 857
593 858
594 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 859 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
595 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 860 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
596 Code* code = NULL; 861 Code* code = NULL;
597 if (kind == Code::LOAD_IC) { 862 if (kind == Code::LOAD_IC) {
598 code = Builtins::builtin(Builtins::LoadIC_Miss); 863 code = Builtins::builtin(Builtins::LoadIC_Miss);
599 } else { 864 } else {
600 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); 865 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
601 } 866 }
602 867
603 Handle<Code> ic(code); 868 Handle<Code> ic(code);
604 __ jmp(ic, RelocInfo::CODE_TARGET); 869 __ jmp(ic, RelocInfo::CODE_TARGET);
605 } 870 }
606 871
607 872
873 // Both name_reg and receiver_reg are preserved on jumps to miss_label,
874 // but may be destroyed if store is successful.
608 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 875 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
609 Builtins::Name storage_extend,
610 JSObject* object, 876 JSObject* object,
611 int index, 877 int index,
612 Map* transition, 878 Map* transition,
613 Register receiver_reg, 879 Register receiver_reg,
614 Register name_reg, 880 Register name_reg,
615 Register scratch, 881 Register scratch,
616 Label* miss_label) { 882 Label* miss_label) {
617 // Check that the object isn't a smi. 883 // Check that the object isn't a smi.
618 __ test(receiver_reg, Immediate(kSmiTagMask)); 884 __ test(receiver_reg, Immediate(kSmiTagMask));
619 __ j(zero, miss_label, not_taken); 885 __ j(zero, miss_label, not_taken);
620 886
621 // Check that the map of the object hasn't changed. 887 // Check that the map of the object hasn't changed.
622 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), 888 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
623 Immediate(Handle<Map>(object->map()))); 889 Immediate(Handle<Map>(object->map())));
624 __ j(not_equal, miss_label, not_taken); 890 __ j(not_equal, miss_label, not_taken);
625 891
626 // Perform global security token check if needed. 892 // Perform global security token check if needed.
627 if (object->IsJSGlobalProxy()) { 893 if (object->IsJSGlobalProxy()) {
628 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 894 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
629 } 895 }
630 896
631 // Stub never generated for non-global objects that require access 897 // Stub never generated for non-global objects that require access
632 // checks. 898 // checks.
633 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 899 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
634 900
635 // Perform map transition for the receiver if necessary. 901 // Perform map transition for the receiver if necessary.
636 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { 902 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
637 // The properties must be extended before we can store the value. 903 // The properties must be extended before we can store the value.
638 // We jump to a runtime call that extends the properties array. 904 // We jump to a runtime call that extends the properties array.
639 __ mov(ecx, Immediate(Handle<Map>(transition))); 905 __ pop(scratch); // Return address.
640 Handle<Code> ic(Builtins::builtin(storage_extend)); 906 __ push(receiver_reg);
641 __ jmp(ic, RelocInfo::CODE_TARGET); 907 __ push(Immediate(Handle<Map>(transition)));
908 __ push(eax);
909 __ push(scratch);
910 __ TailCallRuntime(
911 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1);
642 return; 912 return;
643 } 913 }
644 914
645 if (transition != NULL) { 915 if (transition != NULL) {
646 // Update the map of the object; no write barrier updating is 916 // Update the map of the object; no write barrier updating is
647 // needed because the map is never in new space. 917 // needed because the map is never in new space.
648 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), 918 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
649 Immediate(Handle<Map>(transition))); 919 Immediate(Handle<Map>(transition)));
650 } 920 }
651 921
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 #undef __ 954 #undef __
685 #define __ ACCESS_MASM(masm()) 955 #define __ ACCESS_MASM(masm())
686 956
687 957
688 Register StubCompiler::CheckPrototypes(JSObject* object, 958 Register StubCompiler::CheckPrototypes(JSObject* object,
689 Register object_reg, 959 Register object_reg,
690 JSObject* holder, 960 JSObject* holder,
691 Register holder_reg, 961 Register holder_reg,
692 Register scratch, 962 Register scratch,
693 String* name, 963 String* name,
964 int push_at_depth,
694 Label* miss) { 965 Label* miss) {
695 // Check that the maps haven't changed. 966 // Check that the maps haven't changed.
696 Register result = 967 Register result =
697 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); 968 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch,
969 push_at_depth, miss);
698 970
699 // If we've skipped any global objects, it's not enough to verify 971 // If we've skipped any global objects, it's not enough to verify
700 // that their maps haven't changed. 972 // that their maps haven't changed.
701 while (object != holder) { 973 while (object != holder) {
702 if (object->IsGlobalObject()) { 974 if (object->IsGlobalObject()) {
703 GlobalObject* global = GlobalObject::cast(object); 975 GlobalObject* global = GlobalObject::cast(object);
704 Object* probe = global->EnsurePropertyCell(name); 976 Object* probe = global->EnsurePropertyCell(name);
705 if (probe->IsFailure()) { 977 if (probe->IsFailure()) {
706 set_failure(Failure::cast(probe)); 978 set_failure(Failure::cast(probe));
707 return result; 979 return result;
708 } 980 }
709 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); 981 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
710 ASSERT(cell->value()->IsTheHole()); 982 ASSERT(cell->value()->IsTheHole());
711 __ mov(scratch, Immediate(Handle<Object>(cell))); 983 __ mov(scratch, Immediate(Handle<Object>(cell)));
712 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), 984 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
713 Immediate(Factory::the_hole_value())); 985 Immediate(Factory::the_hole_value()));
714 __ j(not_equal, miss, not_taken); 986 __ j(not_equal, miss, not_taken);
715 } 987 }
716 object = JSObject::cast(object->GetPrototype()); 988 object = JSObject::cast(object->GetPrototype());
717 } 989 }
718 990
719 // Return the register containin the holder. 991 // Return the register containing the holder.
720 return result; 992 return result;
721 } 993 }
722 994
723 995
724 void StubCompiler::GenerateLoadField(JSObject* object, 996 void StubCompiler::GenerateLoadField(JSObject* object,
725 JSObject* holder, 997 JSObject* holder,
726 Register receiver, 998 Register receiver,
727 Register scratch1, 999 Register scratch1,
728 Register scratch2, 1000 Register scratch2,
729 int index, 1001 int index,
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 __ LeaveInternalFrame(); 1152 __ LeaveInternalFrame();
881 1153
882 // Do a tail-call of the compiled function. 1154 // Do a tail-call of the compiled function.
883 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize)); 1155 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize));
884 __ jmp(Operand(ecx)); 1156 __ jmp(Operand(ecx));
885 1157
886 return GetCodeWithFlags(flags, "LazyCompileStub"); 1158 return GetCodeWithFlags(flags, "LazyCompileStub");
887 } 1159 }
888 1160
889 1161
890 Object* CallStubCompiler::CompileCallField(Object* object, 1162 Object* CallStubCompiler::CompileCallField(JSObject* object,
891 JSObject* holder, 1163 JSObject* holder,
892 int index, 1164 int index,
893 String* name) { 1165 String* name) {
894 // ----------- S t a t e ------------- 1166 // ----------- S t a t e -------------
895 // -- ecx : name 1167 // -- ecx : name
896 // -- esp[0] : return address 1168 // -- esp[0] : return address
897 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1169 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
898 // -- ... 1170 // -- ...
899 // -- esp[(argc + 1) * 4] : receiver 1171 // -- esp[(argc + 1) * 4] : receiver
900 // ----------------------------------- 1172 // -----------------------------------
901 Label miss; 1173 Label miss;
902 1174
903 // Get the receiver from the stack. 1175 // Get the receiver from the stack.
904 const int argc = arguments().immediate(); 1176 const int argc = arguments().immediate();
905 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1177 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
906 1178
907 // Check that the receiver isn't a smi. 1179 // Check that the receiver isn't a smi.
908 __ test(edx, Immediate(kSmiTagMask)); 1180 __ test(edx, Immediate(kSmiTagMask));
909 __ j(zero, &miss, not_taken); 1181 __ j(zero, &miss, not_taken);
910 1182
911 // Do the right check and compute the holder register. 1183 // Do the right check and compute the holder register.
912 Register reg = 1184 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, name, &miss);
913 CheckPrototypes(JSObject::cast(object), edx, holder,
914 ebx, eax, name, &miss);
915 1185
916 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); 1186 GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
917 1187
918 // Check that the function really is a function. 1188 // Check that the function really is a function.
919 __ test(edi, Immediate(kSmiTagMask)); 1189 __ test(edi, Immediate(kSmiTagMask));
920 __ j(zero, &miss, not_taken); 1190 __ j(zero, &miss, not_taken);
921 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1191 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
922 __ j(not_equal, &miss, not_taken); 1192 __ j(not_equal, &miss, not_taken);
923 1193
924 // Patch the receiver on the stack with the global proxy if 1194 // Patch the receiver on the stack with the global proxy if
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 // Check that the receiver isn't a smi. 1232 // Check that the receiver isn't a smi.
963 if (check != NUMBER_CHECK) { 1233 if (check != NUMBER_CHECK) {
964 __ test(edx, Immediate(kSmiTagMask)); 1234 __ test(edx, Immediate(kSmiTagMask));
965 __ j(zero, &miss, not_taken); 1235 __ j(zero, &miss, not_taken);
966 } 1236 }
967 1237
968 // Make sure that it's okay not to patch the on stack receiver 1238 // Make sure that it's okay not to patch the on stack receiver
969 // unless we're doing a receiver map check. 1239 // unless we're doing a receiver map check.
970 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 1240 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
971 1241
1242 CallOptimization optimization(function);
1243 int depth = kInvalidProtoDepth;
1244
972 switch (check) { 1245 switch (check) {
973 case RECEIVER_MAP_CHECK: 1246 case RECEIVER_MAP_CHECK:
1247 __ IncrementCounter(&Counters::call_const, 1);
1248
1249 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
1250 depth = optimization.GetPrototypeDepthOfExpectedType(
1251 JSObject::cast(object), holder);
1252 }
1253
1254 if (depth != kInvalidProtoDepth) {
1255 __ IncrementCounter(&Counters::call_const_fast_api, 1);
1256 ReserveSpaceForFastApiCall(masm(), eax);
1257 }
1258
974 // Check that the maps haven't changed. 1259 // Check that the maps haven't changed.
975 CheckPrototypes(JSObject::cast(object), edx, holder, 1260 CheckPrototypes(JSObject::cast(object), edx, holder,
976 ebx, eax, name, &miss); 1261 ebx, eax, name, depth, &miss);
977 1262
978 // Patch the receiver on the stack with the global proxy if 1263 // Patch the receiver on the stack with the global proxy if
979 // necessary. 1264 // necessary.
980 if (object->IsGlobalObject()) { 1265 if (object->IsGlobalObject()) {
1266 ASSERT(depth == kInvalidProtoDepth);
981 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1267 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
982 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1268 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
983 } 1269 }
984 break; 1270 break;
985 1271
986 case STRING_CHECK: 1272 case STRING_CHECK:
987 if (!function->IsBuiltin()) { 1273 if (!function->IsBuiltin()) {
988 // Calling non-builtins with a value as receiver requires boxing. 1274 // Calling non-builtins with a value as receiver requires boxing.
989 __ jmp(&miss); 1275 __ jmp(&miss);
990 } else { 1276 } else {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 // Check that the object is in fast mode (not dictionary). 1341 // Check that the object is in fast mode (not dictionary).
1056 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 1342 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1057 Immediate(Factory::fixed_array_map())); 1343 Immediate(Factory::fixed_array_map()));
1058 __ j(not_equal, &miss, not_taken); 1344 __ j(not_equal, &miss, not_taken);
1059 break; 1345 break;
1060 1346
1061 default: 1347 default:
1062 UNREACHABLE(); 1348 UNREACHABLE();
1063 } 1349 }
1064 1350
1065 // Get the function and setup the context. 1351 if (depth != kInvalidProtoDepth) {
1066 __ mov(edi, Immediate(Handle<JSFunction>(function))); 1352 GenerateFastApiCall(masm(), optimization, argc);
1067 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 1353 } else {
1068 1354 __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
1069 // Jump to the cached code (tail call). 1355 }
1070 ASSERT(function->is_compiled());
1071 Handle<Code> code(function->code());
1072 ParameterCount expected(function->shared()->formal_parameter_count());
1073 __ InvokeCode(code, expected, arguments(),
1074 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
1075 1356
1076 // Handle call cache miss. 1357 // Handle call cache miss.
1077 __ bind(&miss); 1358 __ bind(&miss);
1359 if (depth != kInvalidProtoDepth) {
1360 FreeSpaceForFastApiCall(masm(), eax);
1361 }
1078 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 1362 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
1079 __ jmp(ic, RelocInfo::CODE_TARGET); 1363 __ jmp(ic, RelocInfo::CODE_TARGET);
1080 1364
1081 // Return the generated code. 1365 // Return the generated code.
1082 String* function_name = NULL; 1366 String* function_name = NULL;
1083 if (function->shared()->name()->IsString()) { 1367 if (function->shared()->name()->IsString()) {
1084 function_name = String::cast(function->shared()->name()); 1368 function_name = String::cast(function->shared()->name());
1085 } 1369 }
1086 return GetCode(CONSTANT_FUNCTION, function_name); 1370 return GetCode(CONSTANT_FUNCTION, function_name);
1087 } 1371 }
1088 1372
1089 1373
1090 Object* CallStubCompiler::CompileCallInterceptor(Object* object, 1374 Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
1091 JSObject* holder, 1375 JSObject* holder,
1092 String* name) { 1376 String* name) {
1093 // ----------- S t a t e ------------- 1377 // ----------- S t a t e -------------
1094 // -- ecx : name 1378 // -- ecx : name
1095 // -- esp[0] : return address 1379 // -- esp[0] : return address
1096 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1380 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1097 // -- ... 1381 // -- ...
1098 // -- esp[(argc + 1) * 4] : receiver 1382 // -- esp[(argc + 1) * 4] : receiver
1099 // ----------------------------------- 1383 // -----------------------------------
1100 Label miss; 1384 Label miss;
1101 1385
1102 // Get the number of arguments. 1386 // Get the number of arguments.
1103 const int argc = arguments().immediate(); 1387 const int argc = arguments().immediate();
1104 1388
1105 LookupResult lookup; 1389 LookupResult lookup;
1106 LookupPostInterceptor(holder, name, &lookup); 1390 LookupPostInterceptor(holder, name, &lookup);
1107 1391
1108 // Get the receiver from the stack. 1392 // Get the receiver from the stack.
1109 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1393 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1110 1394
1111 CallInterceptorCompiler compiler(arguments(), ecx); 1395 CallInterceptorCompiler compiler(this, arguments(), ecx);
1112 CompileLoadInterceptor(&compiler, 1396 compiler.Compile(masm(),
1113 this, 1397 object,
1114 masm(), 1398 holder,
1115 JSObject::cast(object), 1399 name,
1116 holder, 1400 &lookup,
1117 name, 1401 edx,
1118 &lookup, 1402 ebx,
1119 edx, 1403 edi,
1120 ebx, 1404 &miss);
1121 edi,
1122 &miss);
1123 1405
1124 // Restore receiver. 1406 // Restore receiver.
1125 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1407 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1126 1408
1127 // Check that the function really is a function. 1409 // Check that the function really is a function.
1128 __ test(eax, Immediate(kSmiTagMask)); 1410 __ test(eax, Immediate(kSmiTagMask));
1129 __ j(zero, &miss, not_taken); 1411 __ j(zero, &miss, not_taken);
1130 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 1412 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
1131 __ j(not_equal, &miss, not_taken); 1413 __ j(not_equal, &miss, not_taken);
1132 1414
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1242 // ----------- S t a t e ------------- 1524 // ----------- S t a t e -------------
1243 // -- eax : value 1525 // -- eax : value
1244 // -- ecx : name 1526 // -- ecx : name
1245 // -- edx : receiver 1527 // -- edx : receiver
1246 // -- esp[0] : return address 1528 // -- esp[0] : return address
1247 // ----------------------------------- 1529 // -----------------------------------
1248 Label miss; 1530 Label miss;
1249 1531
1250 // Generate store field code. Trashes the name register. 1532 // Generate store field code. Trashes the name register.
1251 GenerateStoreField(masm(), 1533 GenerateStoreField(masm(),
1252 Builtins::StoreIC_ExtendStorage,
1253 object, 1534 object,
1254 index, 1535 index,
1255 transition, 1536 transition,
1256 edx, ecx, ebx, 1537 edx, ecx, ebx,
1257 &miss); 1538 &miss);
1258 1539
1259 // Handle store cache miss. 1540 // Handle store cache miss.
1260 __ bind(&miss); 1541 __ bind(&miss);
1261 __ mov(ecx, Immediate(Handle<String>(name))); // restore name 1542 __ mov(ecx, Immediate(Handle<String>(name))); // restore name
1262 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 1543 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 1697
1417 __ IncrementCounter(&Counters::keyed_store_field, 1); 1698 __ IncrementCounter(&Counters::keyed_store_field, 1);
1418 1699
1419 // Get the name from the stack. 1700 // Get the name from the stack.
1420 __ mov(ecx, Operand(esp, 1 * kPointerSize)); 1701 __ mov(ecx, Operand(esp, 1 * kPointerSize));
1421 // Check that the name has not changed. 1702 // Check that the name has not changed.
1422 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); 1703 __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
1423 __ j(not_equal, &miss, not_taken); 1704 __ j(not_equal, &miss, not_taken);
1424 1705
1425 // Get the object from the stack. 1706 // Get the object from the stack.
1426 __ mov(ebx, Operand(esp, 2 * kPointerSize)); 1707 __ mov(edx, Operand(esp, 2 * kPointerSize));
1427 1708
1428 // Generate store field code. Trashes the name register. 1709 // Generate store field code. Trashes the name register.
1429 GenerateStoreField(masm(), 1710 GenerateStoreField(masm(),
1430 Builtins::KeyedStoreIC_ExtendStorage,
1431 object, 1711 object,
1432 index, 1712 index,
1433 transition, 1713 transition,
1434 ebx, ecx, edx, 1714 edx, ecx, ebx,
1435 &miss); 1715 &miss);
1436 1716
1437 // Handle store cache miss. 1717 // Handle store cache miss.
1438 __ bind(&miss); 1718 __ bind(&miss);
1439 __ DecrementCounter(&Counters::keyed_store_field, 1); 1719 __ DecrementCounter(&Counters::keyed_store_field, 1);
1440 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 1720 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1441 __ jmp(ic, RelocInfo::CODE_TARGET); 1721 __ jmp(ic, RelocInfo::CODE_TARGET);
1442 1722
1443 // Return the generated code. 1723 // Return the generated code.
1444 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 1724 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
1445 } 1725 }
1446 1726
1447 1727
1448 1728
1449 Object* LoadStubCompiler::CompileLoadField(JSObject* object, 1729 Object* LoadStubCompiler::CompileLoadField(JSObject* object,
1450 JSObject* holder, 1730 JSObject* holder,
1451 int index, 1731 int index,
1452 String* name) { 1732 String* name) {
1453 // ----------- S t a t e ------------- 1733 // ----------- S t a t e -------------
1734 // -- eax : receiver
1454 // -- ecx : name 1735 // -- ecx : name
1455 // -- esp[0] : return address 1736 // -- esp[0] : return address
1456 // -- esp[4] : receiver
1457 // ----------------------------------- 1737 // -----------------------------------
1458 Label miss; 1738 Label miss;
1459 1739
1460 __ mov(eax, Operand(esp, kPointerSize));
1461 GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss); 1740 GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss);
1462 __ bind(&miss); 1741 __ bind(&miss);
1463 GenerateLoadMiss(masm(), Code::LOAD_IC); 1742 GenerateLoadMiss(masm(), Code::LOAD_IC);
1464 1743
1465 // Return the generated code. 1744 // Return the generated code.
1466 return GetCode(FIELD, name); 1745 return GetCode(FIELD, name);
1467 } 1746 }
1468 1747
1469 1748
1470 Object* LoadStubCompiler::CompileLoadCallback(String* name, 1749 Object* LoadStubCompiler::CompileLoadCallback(String* name,
1471 JSObject* object, 1750 JSObject* object,
1472 JSObject* holder, 1751 JSObject* holder,
1473 AccessorInfo* callback) { 1752 AccessorInfo* callback) {
1474 // ----------- S t a t e ------------- 1753 // ----------- S t a t e -------------
1754 // -- eax : receiver
1475 // -- ecx : name 1755 // -- ecx : name
1476 // -- esp[0] : return address 1756 // -- esp[0] : return address
1477 // -- esp[4] : receiver
1478 // ----------------------------------- 1757 // -----------------------------------
1479 Label miss; 1758 Label miss;
1480 1759
1481 __ mov(eax, Operand(esp, kPointerSize));
1482 Failure* failure = Failure::InternalError(); 1760 Failure* failure = Failure::InternalError();
1483 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, 1761 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
1484 callback, name, &miss, &failure); 1762 callback, name, &miss, &failure);
1485 if (!success) return failure; 1763 if (!success) return failure;
1486 1764
1487 __ bind(&miss); 1765 __ bind(&miss);
1488 GenerateLoadMiss(masm(), Code::LOAD_IC); 1766 GenerateLoadMiss(masm(), Code::LOAD_IC);
1489 1767
1490 // Return the generated code. 1768 // Return the generated code.
1491 return GetCode(CALLBACKS, name); 1769 return GetCode(CALLBACKS, name);
1492 } 1770 }
1493 1771
1494 1772
1495 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, 1773 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
1496 JSObject* holder, 1774 JSObject* holder,
1497 Object* value, 1775 Object* value,
1498 String* name) { 1776 String* name) {
1499 // ----------- S t a t e ------------- 1777 // ----------- S t a t e -------------
1778 // -- eax : receiver
1500 // -- ecx : name 1779 // -- ecx : name
1501 // -- esp[0] : return address 1780 // -- esp[0] : return address
1502 // -- esp[4] : receiver
1503 // ----------------------------------- 1781 // -----------------------------------
1504 Label miss; 1782 Label miss;
1505 1783
1506 __ mov(eax, Operand(esp, kPointerSize));
1507 GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss); 1784 GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss);
1508 __ bind(&miss); 1785 __ bind(&miss);
1509 GenerateLoadMiss(masm(), Code::LOAD_IC); 1786 GenerateLoadMiss(masm(), Code::LOAD_IC);
1510 1787
1511 // Return the generated code. 1788 // Return the generated code.
1512 return GetCode(CONSTANT_FUNCTION, name); 1789 return GetCode(CONSTANT_FUNCTION, name);
1513 } 1790 }
1514 1791
1515 1792
1516 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 1793 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1517 JSObject* holder, 1794 JSObject* holder,
1518 String* name) { 1795 String* name) {
1519 // ----------- S t a t e ------------- 1796 // ----------- S t a t e -------------
1797 // -- eax : receiver
1520 // -- ecx : name 1798 // -- ecx : name
1521 // -- esp[0] : return address 1799 // -- esp[0] : return address
1522 // -- esp[4] : receiver
1523 // ----------------------------------- 1800 // -----------------------------------
1524 Label miss; 1801 Label miss;
1525 1802
1526 LookupResult lookup; 1803 LookupResult lookup;
1527 LookupPostInterceptor(holder, name, &lookup); 1804 LookupPostInterceptor(holder, name, &lookup);
1528 1805
1529 __ mov(eax, Operand(esp, kPointerSize));
1530 // TODO(368): Compile in the whole chain: all the interceptors in 1806 // TODO(368): Compile in the whole chain: all the interceptors in
1531 // prototypes and ultimate answer. 1807 // prototypes and ultimate answer.
1532 GenerateLoadInterceptor(receiver, 1808 GenerateLoadInterceptor(receiver,
1533 holder, 1809 holder,
1534 &lookup, 1810 &lookup,
1535 eax, 1811 eax,
1536 ecx, 1812 ecx,
1537 edx, 1813 edx,
1538 ebx, 1814 ebx,
1539 name, 1815 name,
1540 &miss); 1816 &miss);
1541 1817
1542 __ bind(&miss); 1818 __ bind(&miss);
1543 GenerateLoadMiss(masm(), Code::LOAD_IC); 1819 GenerateLoadMiss(masm(), Code::LOAD_IC);
1544 1820
1545 // Return the generated code. 1821 // Return the generated code.
1546 return GetCode(INTERCEPTOR, name); 1822 return GetCode(INTERCEPTOR, name);
1547 } 1823 }
1548 1824
1549 1825
1550 Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, 1826 Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
1551 GlobalObject* holder, 1827 GlobalObject* holder,
1552 JSGlobalPropertyCell* cell, 1828 JSGlobalPropertyCell* cell,
1553 String* name, 1829 String* name,
1554 bool is_dont_delete) { 1830 bool is_dont_delete) {
1555 // ----------- S t a t e ------------- 1831 // ----------- S t a t e -------------
1832 // -- eax : receiver
1556 // -- ecx : name 1833 // -- ecx : name
1557 // -- esp[0] : return address 1834 // -- esp[0] : return address
1558 // -- esp[4] : receiver
1559 // ----------------------------------- 1835 // -----------------------------------
1560 Label miss; 1836 Label miss;
1561 1837
1562 // Get the receiver from the stack.
1563 __ mov(eax, Operand(esp, kPointerSize));
1564
1565 // If the object is the holder then we know that it's a global 1838 // If the object is the holder then we know that it's a global
1566 // object which can only happen for contextual loads. In this case, 1839 // object which can only happen for contextual loads. In this case,
1567 // the receiver cannot be a smi. 1840 // the receiver cannot be a smi.
1568 if (object != holder) { 1841 if (object != holder) {
1569 __ test(eax, Immediate(kSmiTagMask)); 1842 __ test(eax, Immediate(kSmiTagMask));
1570 __ j(zero, &miss, not_taken); 1843 __ j(zero, &miss, not_taken);
1571 } 1844 }
1572 1845
1573 // Check that the maps haven't changed. 1846 // Check that the maps haven't changed.
1574 CheckPrototypes(object, eax, holder, ebx, edx, name, &miss); 1847 CheckPrototypes(object, eax, holder, ebx, edx, name, &miss);
1575 1848
1576 // Get the value from the cell. 1849 // Get the value from the cell.
1577 __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell))); 1850 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1578 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); 1851 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
1579 1852
1580 // Check for deleted property if property can actually be deleted. 1853 // Check for deleted property if property can actually be deleted.
1581 if (!is_dont_delete) { 1854 if (!is_dont_delete) {
1582 __ cmp(eax, Factory::the_hole_value()); 1855 __ cmp(ebx, Factory::the_hole_value());
1583 __ j(equal, &miss, not_taken); 1856 __ j(equal, &miss, not_taken);
1584 } else if (FLAG_debug_code) { 1857 } else if (FLAG_debug_code) {
1585 __ cmp(eax, Factory::the_hole_value()); 1858 __ cmp(ebx, Factory::the_hole_value());
1586 __ Check(not_equal, "DontDelete cells can't contain the hole"); 1859 __ Check(not_equal, "DontDelete cells can't contain the hole");
1587 } 1860 }
1588 1861
1589 __ IncrementCounter(&Counters::named_load_global_inline, 1); 1862 __ IncrementCounter(&Counters::named_load_global_inline, 1);
1863 __ mov(eax, ebx);
1590 __ ret(0); 1864 __ ret(0);
1591 1865
1592 __ bind(&miss); 1866 __ bind(&miss);
1593 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1); 1867 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
1594 GenerateLoadMiss(masm(), Code::LOAD_IC); 1868 GenerateLoadMiss(masm(), Code::LOAD_IC);
1595 1869
1596 // Return the generated code. 1870 // Return the generated code.
1597 return GetCode(NORMAL, name); 1871 return GetCode(NORMAL, name);
1598 } 1872 }
1599 1873
1600 1874
1601 Object* KeyedLoadStubCompiler::CompileLoadField(String* name, 1875 Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
1602 JSObject* receiver, 1876 JSObject* receiver,
1603 JSObject* holder, 1877 JSObject* holder,
1604 int index) { 1878 int index) {
1605 // ----------- S t a t e ------------- 1879 // ----------- S t a t e -------------
1880 // -- eax : key
1881 // -- edx : receiver
1606 // -- esp[0] : return address 1882 // -- esp[0] : return address
1607 // -- esp[4] : name
1608 // -- esp[8] : receiver
1609 // ----------------------------------- 1883 // -----------------------------------
1610 Label miss; 1884 Label miss;
1611 1885
1612 __ mov(eax, Operand(esp, kPointerSize));
1613 __ mov(ecx, Operand(esp, 2 * kPointerSize));
1614 __ IncrementCounter(&Counters::keyed_load_field, 1); 1886 __ IncrementCounter(&Counters::keyed_load_field, 1);
1615 1887
1616 // Check that the name has not changed. 1888 // Check that the name has not changed.
1617 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 1889 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1618 __ j(not_equal, &miss, not_taken); 1890 __ j(not_equal, &miss, not_taken);
1619 1891
1620 GenerateLoadField(receiver, holder, ecx, ebx, edx, index, name, &miss); 1892 GenerateLoadField(receiver, holder, edx, ebx, ecx, index, name, &miss);
1621 1893
1622 __ bind(&miss); 1894 __ bind(&miss);
1623 __ DecrementCounter(&Counters::keyed_load_field, 1); 1895 __ DecrementCounter(&Counters::keyed_load_field, 1);
1624 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1896 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1625 1897
1626 // Return the generated code. 1898 // Return the generated code.
1627 return GetCode(FIELD, name); 1899 return GetCode(FIELD, name);
1628 } 1900 }
1629 1901
1630 1902
1631 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, 1903 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1632 JSObject* receiver, 1904 JSObject* receiver,
1633 JSObject* holder, 1905 JSObject* holder,
1634 AccessorInfo* callback) { 1906 AccessorInfo* callback) {
1635 // ----------- S t a t e ------------- 1907 // ----------- S t a t e -------------
1908 // -- eax : key
1909 // -- edx : receiver
1636 // -- esp[0] : return address 1910 // -- esp[0] : return address
1637 // -- esp[4] : name
1638 // -- esp[8] : receiver
1639 // ----------------------------------- 1911 // -----------------------------------
1640 Label miss; 1912 Label miss;
1641 1913
1642 __ mov(eax, Operand(esp, kPointerSize));
1643 __ mov(ecx, Operand(esp, 2 * kPointerSize));
1644 __ IncrementCounter(&Counters::keyed_load_callback, 1); 1914 __ IncrementCounter(&Counters::keyed_load_callback, 1);
1645 1915
1646 // Check that the name has not changed. 1916 // Check that the name has not changed.
1647 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 1917 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1648 __ j(not_equal, &miss, not_taken); 1918 __ j(not_equal, &miss, not_taken);
1649 1919
1650 Failure* failure = Failure::InternalError(); 1920 Failure* failure = Failure::InternalError();
1651 bool success = GenerateLoadCallback(receiver, holder, ecx, eax, ebx, edx, 1921 bool success = GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx,
1652 callback, name, &miss, &failure); 1922 callback, name, &miss, &failure);
1653 if (!success) return failure; 1923 if (!success) return failure;
1654 1924
1655 __ bind(&miss); 1925 __ bind(&miss);
1656 __ DecrementCounter(&Counters::keyed_load_callback, 1); 1926 __ DecrementCounter(&Counters::keyed_load_callback, 1);
1657 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1927 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1658 1928
1659 // Return the generated code. 1929 // Return the generated code.
1660 return GetCode(CALLBACKS, name); 1930 return GetCode(CALLBACKS, name);
1661 } 1931 }
1662 1932
1663 1933
1664 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, 1934 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1665 JSObject* receiver, 1935 JSObject* receiver,
1666 JSObject* holder, 1936 JSObject* holder,
1667 Object* value) { 1937 Object* value) {
1668 // ----------- S t a t e ------------- 1938 // ----------- S t a t e -------------
1939 // -- eax : key
1940 // -- edx : receiver
1669 // -- esp[0] : return address 1941 // -- esp[0] : return address
1670 // -- esp[4] : name
1671 // -- esp[8] : receiver
1672 // ----------------------------------- 1942 // -----------------------------------
1673 Label miss; 1943 Label miss;
1674 1944
1675 __ mov(eax, Operand(esp, kPointerSize));
1676 __ mov(ecx, Operand(esp, 2 * kPointerSize));
1677 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); 1945 __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
1678 1946
1679 // Check that the name has not changed. 1947 // Check that the name has not changed.
1680 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 1948 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1681 __ j(not_equal, &miss, not_taken); 1949 __ j(not_equal, &miss, not_taken);
1682 1950
1683 GenerateLoadConstant(receiver, holder, ecx, ebx, edx, 1951 GenerateLoadConstant(receiver, holder, edx, ebx, ecx,
1684 value, name, &miss); 1952 value, name, &miss);
1685 __ bind(&miss); 1953 __ bind(&miss);
1686 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); 1954 __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
1687 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1955 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1688 1956
1689 // Return the generated code. 1957 // Return the generated code.
1690 return GetCode(CONSTANT_FUNCTION, name); 1958 return GetCode(CONSTANT_FUNCTION, name);
1691 } 1959 }
1692 1960
1693 1961
1694 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 1962 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1695 JSObject* holder, 1963 JSObject* holder,
1696 String* name) { 1964 String* name) {
1697 // ----------- S t a t e ------------- 1965 // ----------- S t a t e -------------
1966 // -- eax : key
1967 // -- edx : receiver
1698 // -- esp[0] : return address 1968 // -- esp[0] : return address
1699 // -- esp[4] : name
1700 // -- esp[8] : receiver
1701 // ----------------------------------- 1969 // -----------------------------------
1702 Label miss; 1970 Label miss;
1703 1971
1704 __ mov(eax, Operand(esp, kPointerSize));
1705 __ mov(ecx, Operand(esp, 2 * kPointerSize));
1706 __ IncrementCounter(&Counters::keyed_load_interceptor, 1); 1972 __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
1707 1973
1708 // Check that the name has not changed. 1974 // Check that the name has not changed.
1709 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 1975 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1710 __ j(not_equal, &miss, not_taken); 1976 __ j(not_equal, &miss, not_taken);
1711 1977
1712 LookupResult lookup; 1978 LookupResult lookup;
1713 LookupPostInterceptor(holder, name, &lookup); 1979 LookupPostInterceptor(holder, name, &lookup);
1714 GenerateLoadInterceptor(receiver, 1980 GenerateLoadInterceptor(receiver,
1715 holder, 1981 holder,
1716 &lookup, 1982 &lookup,
1983 edx,
1984 eax,
1717 ecx, 1985 ecx,
1718 eax,
1719 edx,
1720 ebx, 1986 ebx,
1721 name, 1987 name,
1722 &miss); 1988 &miss);
1723 __ bind(&miss); 1989 __ bind(&miss);
1724 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); 1990 __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
1725 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1991 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1726 1992
1727 // Return the generated code. 1993 // Return the generated code.
1728 return GetCode(INTERCEPTOR, name); 1994 return GetCode(INTERCEPTOR, name);
1729 } 1995 }
1730 1996
1731 1997
1732 1998
1733 1999
1734 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { 2000 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
1735 // ----------- S t a t e ------------- 2001 // ----------- S t a t e -------------
2002 // -- eax : key
2003 // -- edx : receiver
1736 // -- esp[0] : return address 2004 // -- esp[0] : return address
1737 // -- esp[4] : name
1738 // -- esp[8] : receiver
1739 // ----------------------------------- 2005 // -----------------------------------
1740 Label miss; 2006 Label miss;
1741 2007
1742 __ mov(eax, Operand(esp, kPointerSize));
1743 __ mov(ecx, Operand(esp, 2 * kPointerSize));
1744 __ IncrementCounter(&Counters::keyed_load_array_length, 1); 2008 __ IncrementCounter(&Counters::keyed_load_array_length, 1);
1745 2009
1746 // Check that the name has not changed. 2010 // Check that the name has not changed.
1747 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2011 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1748 __ j(not_equal, &miss, not_taken); 2012 __ j(not_equal, &miss, not_taken);
1749 2013
1750 GenerateLoadArrayLength(masm(), ecx, edx, &miss); 2014 GenerateLoadArrayLength(masm(), edx, ecx, &miss);
1751 __ bind(&miss); 2015 __ bind(&miss);
1752 __ DecrementCounter(&Counters::keyed_load_array_length, 1); 2016 __ DecrementCounter(&Counters::keyed_load_array_length, 1);
1753 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2017 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1754 2018
1755 // Return the generated code. 2019 // Return the generated code.
1756 return GetCode(CALLBACKS, name); 2020 return GetCode(CALLBACKS, name);
1757 } 2021 }
1758 2022
1759 2023
1760 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { 2024 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
1761 // ----------- S t a t e ------------- 2025 // ----------- S t a t e -------------
2026 // -- eax : key
2027 // -- edx : receiver
1762 // -- esp[0] : return address 2028 // -- esp[0] : return address
1763 // -- esp[4] : name
1764 // -- esp[8] : receiver
1765 // ----------------------------------- 2029 // -----------------------------------
1766 Label miss; 2030 Label miss;
1767 2031
1768 __ mov(eax, Operand(esp, kPointerSize));
1769 __ mov(ecx, Operand(esp, 2 * kPointerSize));
1770 __ IncrementCounter(&Counters::keyed_load_string_length, 1); 2032 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
1771 2033
1772 // Check that the name has not changed. 2034 // Check that the name has not changed.
1773 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2035 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1774 __ j(not_equal, &miss, not_taken); 2036 __ j(not_equal, &miss, not_taken);
1775 2037
1776 GenerateLoadStringLength(masm(), ecx, edx, &miss); 2038 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss);
1777 __ bind(&miss); 2039 __ bind(&miss);
1778 __ DecrementCounter(&Counters::keyed_load_string_length, 1); 2040 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
1779 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2041 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1780 2042
1781 // Return the generated code. 2043 // Return the generated code.
1782 return GetCode(CALLBACKS, name); 2044 return GetCode(CALLBACKS, name);
1783 } 2045 }
1784 2046
1785 2047
1786 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { 2048 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
1787 // ----------- S t a t e ------------- 2049 // ----------- S t a t e -------------
2050 // -- eax : key
2051 // -- edx : receiver
1788 // -- esp[0] : return address 2052 // -- esp[0] : return address
1789 // -- esp[4] : name
1790 // -- esp[8] : receiver
1791 // ----------------------------------- 2053 // -----------------------------------
1792 Label miss; 2054 Label miss;
1793 2055
1794 __ mov(eax, Operand(esp, kPointerSize));
1795 __ mov(ecx, Operand(esp, 2 * kPointerSize));
1796 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1); 2056 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
1797 2057
1798 // Check that the name has not changed. 2058 // Check that the name has not changed.
1799 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2059 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1800 __ j(not_equal, &miss, not_taken); 2060 __ j(not_equal, &miss, not_taken);
1801 2061
1802 GenerateLoadFunctionPrototype(masm(), ecx, edx, ebx, &miss); 2062 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
1803 __ bind(&miss); 2063 __ bind(&miss);
1804 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1); 2064 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
1805 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2065 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1806 2066
1807 // Return the generated code. 2067 // Return the generated code.
1808 return GetCode(CALLBACKS, name); 2068 return GetCode(CALLBACKS, name);
1809 } 2069 }
1810 2070
1811 2071
1812 // Specialized stub for constructing objects from functions which only have only 2072 // Specialized stub for constructing objects from functions which only have only
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1942 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); 2202 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
1943 2203
1944 // Return the generated code. 2204 // Return the generated code.
1945 return GetCode(); 2205 return GetCode();
1946 } 2206 }
1947 2207
1948 2208
1949 #undef __ 2209 #undef __
1950 2210
1951 } } // namespace v8::internal 2211 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ia32/virtual-frame-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698