stub-cache-ia32.cc revision 4515c472dc3e5ed2448a564600976759e569a0a8
1// Copyright 2006-2009 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "ic-inl.h"
31#include "codegen-inl.h"
32#include "stub-cache.h"
33
34namespace v8 {
35namespace internal {
36
37#define __ ACCESS_MASM(masm)
38
39
40static void ProbeTable(MacroAssembler* masm,
41                       Code::Flags flags,
42                       StubCache::Table table,
43                       Register name,
44                       Register offset,
45                       Register extra) {
46  ExternalReference key_offset(SCTableReference::keyReference(table));
47  ExternalReference value_offset(SCTableReference::valueReference(table));
48
49  Label miss;
50
51  if (extra.is_valid()) {
52    // Get the code entry from the cache.
53    __ mov(extra, Operand::StaticArray(offset, times_2, value_offset));
54
55    // Check that the key in the entry matches the name.
56    __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
57    __ j(not_equal, &miss, not_taken);
58
59    // Check that the flags match what we're looking for.
60    __ mov(offset, FieldOperand(extra, Code::kFlagsOffset));
61    __ and_(offset, ~Code::kFlagsNotUsedInLookup);
62    __ cmp(offset, flags);
63    __ j(not_equal, &miss);
64
65    // Jump to the first instruction in the code stub.
66    __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag));
67    __ jmp(Operand(extra));
68
69    __ bind(&miss);
70  } else {
71    // Save the offset on the stack.
72    __ push(offset);
73
74    // Check that the key in the entry matches the name.
75    __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
76    __ j(not_equal, &miss, not_taken);
77
78    // Get the code entry from the cache.
79    __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
80
81    // Check that the flags match what we're looking for.
82    __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
83    __ and_(offset, ~Code::kFlagsNotUsedInLookup);
84    __ cmp(offset, flags);
85    __ j(not_equal, &miss);
86
87    // Restore offset and re-load code entry from cache.
88    __ pop(offset);
89    __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
90
91    // Jump to the first instruction in the code stub.
92    __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag));
93    __ jmp(Operand(offset));
94
95    // Pop at miss.
96    __ bind(&miss);
97    __ pop(offset);
98  }
99}
100
101
102void StubCache::GenerateProbe(MacroAssembler* masm,
103                              Code::Flags flags,
104                              Register receiver,
105                              Register name,
106                              Register scratch,
107                              Register extra) {
108  Label miss;
109
110  // Make sure that code is valid. The shifting code relies on the
111  // entry size being 8.
112  ASSERT(sizeof(Entry) == 8);
113
114  // Make sure the flags does not name a specific type.
115  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
116
117  // Make sure that there are no register conflicts.
118  ASSERT(!scratch.is(receiver));
119  ASSERT(!scratch.is(name));
120  ASSERT(!extra.is(receiver));
121  ASSERT(!extra.is(name));
122  ASSERT(!extra.is(scratch));
123
124  // Check that the receiver isn't a smi.
125  __ test(receiver, Immediate(kSmiTagMask));
126  __ j(zero, &miss, not_taken);
127
128  // Get the map of the receiver and compute the hash.
129  __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
130  __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
131  __ xor_(scratch, flags);
132  __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
133
134  // Probe the primary table.
135  ProbeTable(masm, flags, kPrimary, name, scratch, extra);
136
137  // Primary miss: Compute hash for secondary probe.
138  __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
139  __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
140  __ xor_(scratch, flags);
141  __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
142  __ sub(scratch, Operand(name));
143  __ add(Operand(scratch), Immediate(flags));
144  __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
145
146  // Probe the secondary table.
147  ProbeTable(masm, flags, kSecondary, name, scratch, extra);
148
149  // Cache miss: Fall-through and let caller handle the miss by
150  // entering the runtime system.
151  __ bind(&miss);
152}
153
154
155static 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
171void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
172                                                       int index,
173                                                       Register prototype) {
174  // Load the global or builtins object from the current context.
175  __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
176  // Load the global context from the global or builtins object.
177  __ mov(prototype,
178         FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
179  // Load the function from the global context.
180  __ mov(prototype, Operand(prototype, Context::SlotOffset(index)));
181  // Load the initial map.  The global functions all have initial maps.
182  __ mov(prototype,
183         FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
184  // Load the prototype from the initial map.
185  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
186}
187
188
189void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
190                                           Register receiver,
191                                           Register scratch,
192                                           Label* miss_label) {
193  // Check that the receiver isn't a smi.
194  __ test(receiver, Immediate(kSmiTagMask));
195  __ j(zero, miss_label, not_taken);
196
197  // Check that the object is a JS array.
198  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
199  __ j(not_equal, miss_label, not_taken);
200
201  // Load length directly from the JS array.
202  __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
203  __ ret(0);
204}
205
206
207// Generate code to check if an object is a string.  If the object is
208// a string, the map's instance type is left in the scratch register.
209static void GenerateStringCheck(MacroAssembler* masm,
210                                Register receiver,
211                                Register scratch,
212                                Label* smi,
213                                Label* non_string_object) {
214  // Check that the object isn't a smi.
215  __ test(receiver, Immediate(kSmiTagMask));
216  __ j(zero, smi, not_taken);
217
218  // Check that the object is a string.
219  __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
220  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
221  ASSERT(kNotStringTag != 0);
222  __ test(scratch, Immediate(kNotStringTag));
223  __ j(not_zero, non_string_object, not_taken);
224}
225
226
227void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
228                                            Register receiver,
229                                            Register scratch,
230                                            Label* miss) {
231  Label load_length, check_wrapper;
232
233  // Check if the object is a string leaving the instance type in the
234  // scratch register.
235  GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper);
236
237  // Load length from the string and convert to a smi.
238  __ bind(&load_length);
239  __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
240  __ SmiTag(eax);
241  __ ret(0);
242
243  // Check if the object is a JSValue wrapper.
244  __ bind(&check_wrapper);
245  __ cmp(scratch, JS_VALUE_TYPE);
246  __ j(not_equal, miss, not_taken);
247
248  // Check if the wrapped value is a string and load the length
249  // directly if it is.
250  __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset));
251  GenerateStringCheck(masm, receiver, scratch, miss, miss);
252  __ jmp(&load_length);
253}
254
255
256void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
257                                                 Register receiver,
258                                                 Register scratch1,
259                                                 Register scratch2,
260                                                 Label* miss_label) {
261  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
262  __ mov(eax, Operand(scratch1));
263  __ ret(0);
264}
265
266
267// Load a fast property out of a holder object (src). In-object properties
268// are loaded directly otherwise the property is loaded from the properties
269// fixed array.
270void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
271                                            Register dst, Register src,
272                                            JSObject* holder, int index) {
273  // Adjust for the number of properties stored in the holder.
274  index -= holder->map()->inobject_properties();
275  if (index < 0) {
276    // Get the property straight out of the holder.
277    int offset = holder->map()->instance_size() + (index * kPointerSize);
278    __ mov(dst, FieldOperand(src, offset));
279  } else {
280    // Calculate the offset into the properties array.
281    int offset = index * kPointerSize + FixedArray::kHeaderSize;
282    __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
283    __ mov(dst, FieldOperand(dst, offset));
284  }
285}
286
287
288static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
289                                                   Register receiver,
290                                                   Register holder,
291                                                   Register name,
292                                                   JSObject* holder_obj) {
293  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
294
295  ExternalReference ref =
296      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly));
297  __ mov(eax, Immediate(5));
298  __ mov(ebx, Immediate(ref));
299
300  CEntryStub stub(1);
301  __ CallStub(&stub);
302}
303
304
305template <class Compiler>
306static void CompileLoadInterceptor(Compiler* compiler,
307                                   StubCompiler* stub_compiler,
308                                   MacroAssembler* masm,
309                                   JSObject* object,
310                                   JSObject* holder,
311                                   String* name,
312                                   LookupResult* lookup,
313                                   Register receiver,
314                                   Register scratch1,
315                                   Register scratch2,
316                                   Label* miss) {
317  ASSERT(holder->HasNamedInterceptor());
318  ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
319
320  // Check that the receiver isn't a smi.
321  __ test(receiver, Immediate(kSmiTagMask));
322  __ j(zero, miss, not_taken);
323
324  // Check that the maps haven't changed.
325  Register reg =
326      stub_compiler->CheckPrototypes(object, receiver, holder,
327                                     scratch1, scratch2, name, miss);
328
329  if (lookup->IsValid() && lookup->IsCacheable()) {
330    compiler->CompileCacheable(masm,
331                               stub_compiler,
332                               receiver,
333                               reg,
334                               scratch1,
335                               scratch2,
336                               holder,
337                               lookup,
338                               name,
339                               miss);
340  } else {
341    compiler->CompileRegular(masm,
342                             receiver,
343                             reg,
344                             scratch2,
345                             holder,
346                             miss);
347  }
348}
349
350
351class LoadInterceptorCompiler BASE_EMBEDDED {
352 public:
353  explicit LoadInterceptorCompiler(Register name) : name_(name) {}
354
355  void CompileCacheable(MacroAssembler* masm,
356                        StubCompiler* stub_compiler,
357                        Register receiver,
358                        Register holder,
359                        Register scratch1,
360                        Register scratch2,
361                        JSObject* holder_obj,
362                        LookupResult* lookup,
363                        String* name,
364                        Label* miss_label) {
365    AccessorInfo* callback = 0;
366    bool optimize = false;
367    // So far the most popular follow ups for interceptor loads are FIELD
368    // and CALLBACKS, so inline only them, other cases may be added
369    // later.
370    if (lookup->type() == FIELD) {
371      optimize = true;
372    } else if (lookup->type() == CALLBACKS) {
373      Object* callback_object = lookup->GetCallbackObject();
374      if (callback_object->IsAccessorInfo()) {
375        callback = AccessorInfo::cast(callback_object);
376        optimize = callback->getter() != NULL;
377      }
378    }
379
380    if (!optimize) {
381      CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
382      return;
383    }
384
385    // Note: starting a frame here makes GC aware of pointers pushed below.
386    __ EnterInternalFrame();
387
388    if (lookup->type() == CALLBACKS) {
389      __ push(receiver);
390    }
391    __ push(holder);
392    __ push(name_);
393
394    CompileCallLoadPropertyWithInterceptor(masm,
395                                           receiver,
396                                           holder,
397                                           name_,
398                                           holder_obj);
399
400    Label interceptor_failed;
401    __ cmp(eax, Factory::no_interceptor_result_sentinel());
402    __ j(equal, &interceptor_failed);
403    __ LeaveInternalFrame();
404    __ ret(0);
405
406    __ bind(&interceptor_failed);
407    __ pop(name_);
408    __ pop(holder);
409    if (lookup->type() == CALLBACKS) {
410      __ pop(receiver);
411    }
412
413    __ LeaveInternalFrame();
414
415    if (lookup->type() == FIELD) {
416      holder = stub_compiler->CheckPrototypes(holder_obj, holder,
417                                              lookup->holder(), scratch1,
418                                              scratch2,
419                                              name,
420                                              miss_label);
421      stub_compiler->GenerateFastPropertyLoad(masm, eax,
422                                              holder, lookup->holder(),
423                                              lookup->GetFieldIndex());
424      __ ret(0);
425    } else {
426      ASSERT(lookup->type() == CALLBACKS);
427      ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
428      ASSERT(callback != NULL);
429      ASSERT(callback->getter() != NULL);
430
431      Label cleanup;
432      __ pop(scratch2);
433      __ push(receiver);
434      __ push(scratch2);
435
436      holder = stub_compiler->CheckPrototypes(holder_obj, holder,
437                                              lookup->holder(), scratch1,
438                                              scratch2,
439                                              name,
440                                              &cleanup);
441
442      __ pop(scratch2);  // save old return address
443      __ push(holder);
444      __ mov(holder, Immediate(Handle<AccessorInfo>(callback)));
445      __ push(holder);
446      __ push(FieldOperand(holder, AccessorInfo::kDataOffset));
447      __ push(name_);
448      __ push(scratch2);  // restore old return address
449
450      ExternalReference ref =
451          ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
452      __ TailCallRuntime(ref, 5, 1);
453
454      __ bind(&cleanup);
455      __ pop(scratch1);
456      __ pop(scratch2);
457      __ push(scratch1);
458    }
459  }
460
461
462  void CompileRegular(MacroAssembler* masm,
463                      Register receiver,
464                      Register holder,
465                      Register scratch,
466                      JSObject* holder_obj,
467                      Label* miss_label) {
468    __ pop(scratch);  // save old return address
469    PushInterceptorArguments(masm, receiver, holder, name_, holder_obj);
470    __ push(scratch);  // restore old return address
471
472    ExternalReference ref = ExternalReference(
473        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
474    __ TailCallRuntime(ref, 5, 1);
475  }
476
477 private:
478  Register name_;
479};
480
481
482class CallInterceptorCompiler BASE_EMBEDDED {
483 public:
484  CallInterceptorCompiler(const ParameterCount& arguments, Register name)
485      : arguments_(arguments), argc_(arguments.immediate()), name_(name) {}
486
487  void CompileCacheable(MacroAssembler* masm,
488                        StubCompiler* stub_compiler,
489                        Register receiver,
490                        Register holder,
491                        Register scratch1,
492                        Register scratch2,
493                        JSObject* holder_obj,
494                        LookupResult* lookup,
495                        String* name,
496                        Label* miss_label) {
497    JSFunction* function = 0;
498    bool optimize = false;
499    // So far the most popular case for failed interceptor is
500    // CONSTANT_FUNCTION sitting below.
501    if (lookup->type() == CONSTANT_FUNCTION) {
502      function = lookup->GetConstantFunction();
503      // JSArray holder is a special case for call constant function
504      // (see the corresponding code).
505      if (function->is_compiled() && !holder_obj->IsJSArray()) {
506        optimize = true;
507      }
508    }
509
510    if (!optimize) {
511      CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
512      return;
513    }
514
515    __ EnterInternalFrame();
516    __ push(holder);  // Save the holder.
517    __ push(name_);  // Save the name.
518
519    CompileCallLoadPropertyWithInterceptor(masm,
520                                           receiver,
521                                           holder,
522                                           name_,
523                                           holder_obj);
524
525    __ pop(name_);  // Restore the name.
526    __ pop(receiver);  // Restore the holder.
527    __ LeaveInternalFrame();
528
529    __ cmp(eax, Factory::no_interceptor_result_sentinel());
530    Label invoke;
531    __ j(not_equal, &invoke);
532
533    stub_compiler->CheckPrototypes(holder_obj, receiver,
534                                   lookup->holder(), scratch1,
535                                   scratch2,
536                                   name,
537                                   miss_label);
538    if (lookup->holder()->IsGlobalObject()) {
539      __ mov(edx, Operand(esp, (argc_ + 1) * kPointerSize));
540      __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
541      __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edx);
542    }
543
544    ASSERT(function->is_compiled());
545    // Get the function and setup the context.
546    __ mov(edi, Immediate(Handle<JSFunction>(function)));
547    __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
548
549    // Jump to the cached code (tail call).
550    Handle<Code> code(function->code());
551    ParameterCount expected(function->shared()->formal_parameter_count());
552    __ InvokeCode(code, expected, arguments_,
553                  RelocInfo::CODE_TARGET, JUMP_FUNCTION);
554
555    __ bind(&invoke);
556  }
557
558  void CompileRegular(MacroAssembler* masm,
559                      Register receiver,
560                      Register holder,
561                      Register scratch,
562                      JSObject* holder_obj,
563                      Label* miss_label) {
564    __ EnterInternalFrame();
565    // Save the name_ register across the call.
566    __ push(name_);
567
568    PushInterceptorArguments(masm,
569                             receiver,
570                             holder,
571                             name_,
572                             holder_obj);
573
574    ExternalReference ref = ExternalReference(
575        IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
576    __ mov(eax, Immediate(5));
577    __ mov(ebx, Immediate(ref));
578
579    CEntryStub stub(1);
580    __ CallStub(&stub);
581
582    // Restore the name_ register.
583    __ pop(name_);
584    __ LeaveInternalFrame();
585  }
586
587 private:
588  const ParameterCount& arguments_;
589  int argc_;
590  Register name_;
591};
592
593
594void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
595  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
596  Code* code = NULL;
597  if (kind == Code::LOAD_IC) {
598    code = Builtins::builtin(Builtins::LoadIC_Miss);
599  } else {
600    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
601  }
602
603  Handle<Code> ic(code);
604  __ jmp(ic, RelocInfo::CODE_TARGET);
605}
606
607
608void StubCompiler::GenerateStoreField(MacroAssembler* masm,
609                                      Builtins::Name storage_extend,
610                                      JSObject* object,
611                                      int index,
612                                      Map* transition,
613                                      Register receiver_reg,
614                                      Register name_reg,
615                                      Register scratch,
616                                      Label* miss_label) {
617  // Check that the object isn't a smi.
618  __ test(receiver_reg, Immediate(kSmiTagMask));
619  __ j(zero, miss_label, not_taken);
620
621  // Check that the map of the object hasn't changed.
622  __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
623         Immediate(Handle<Map>(object->map())));
624  __ j(not_equal, miss_label, not_taken);
625
626  // Perform global security token check if needed.
627  if (object->IsJSGlobalProxy()) {
628    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
629  }
630
631  // Stub never generated for non-global objects that require access
632  // checks.
633  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
634
635  // Perform map transition for the receiver if necessary.
636  if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
637    // The properties must be extended before we can store the value.
638    // We jump to a runtime call that extends the properties array.
639    __ mov(ecx, Immediate(Handle<Map>(transition)));
640    Handle<Code> ic(Builtins::builtin(storage_extend));
641    __ jmp(ic, RelocInfo::CODE_TARGET);
642    return;
643  }
644
645  if (transition != NULL) {
646    // Update the map of the object; no write barrier updating is
647    // needed because the map is never in new space.
648    __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
649           Immediate(Handle<Map>(transition)));
650  }
651
652  // Adjust for the number of properties stored in the object. Even in the
653  // face of a transition we can use the old map here because the size of the
654  // object and the number of in-object properties is not going to change.
655  index -= object->map()->inobject_properties();
656
657  if (index < 0) {
658    // Set the property straight into the object.
659    int offset = object->map()->instance_size() + (index * kPointerSize);
660    __ mov(FieldOperand(receiver_reg, offset), eax);
661
662    // Update the write barrier for the array address.
663    // Pass the value being stored in the now unused name_reg.
664    __ mov(name_reg, Operand(eax));
665    __ RecordWrite(receiver_reg, offset, name_reg, scratch);
666  } else {
667    // Write to the properties array.
668    int offset = index * kPointerSize + FixedArray::kHeaderSize;
669    // Get the properties array (optimistically).
670    __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
671    __ mov(FieldOperand(scratch, offset), eax);
672
673    // Update the write barrier for the array address.
674    // Pass the value being stored in the now unused name_reg.
675    __ mov(name_reg, Operand(eax));
676    __ RecordWrite(scratch, offset, name_reg, receiver_reg);
677  }
678
679  // Return the value (register eax).
680  __ ret(0);
681}
682
683
684#undef __
685#define __ ACCESS_MASM(masm())
686
687
688Register StubCompiler::CheckPrototypes(JSObject* object,
689                                       Register object_reg,
690                                       JSObject* holder,
691                                       Register holder_reg,
692                                       Register scratch,
693                                       String* name,
694                                       Label* miss) {
695  // Check that the maps haven't changed.
696  Register result =
697      masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss);
698
699  // If we've skipped any global objects, it's not enough to verify
700  // that their maps haven't changed.
701  while (object != holder) {
702    if (object->IsGlobalObject()) {
703      GlobalObject* global = GlobalObject::cast(object);
704      Object* probe = global->EnsurePropertyCell(name);
705      if (probe->IsFailure()) {
706        set_failure(Failure::cast(probe));
707        return result;
708      }
709      JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
710      ASSERT(cell->value()->IsTheHole());
711      __ mov(scratch, Immediate(Handle<Object>(cell)));
712      __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
713             Immediate(Factory::the_hole_value()));
714      __ j(not_equal, miss, not_taken);
715    }
716    object = JSObject::cast(object->GetPrototype());
717  }
718
719  // Return the register containin the holder.
720  return result;
721}
722
723
724void StubCompiler::GenerateLoadField(JSObject* object,
725                                     JSObject* holder,
726                                     Register receiver,
727                                     Register scratch1,
728                                     Register scratch2,
729                                     int index,
730                                     String* name,
731                                     Label* miss) {
732  // Check that the receiver isn't a smi.
733  __ test(receiver, Immediate(kSmiTagMask));
734  __ j(zero, miss, not_taken);
735
736  // Check the prototype chain.
737  Register reg =
738      CheckPrototypes(object, receiver, holder,
739                      scratch1, scratch2, name, miss);
740
741  // Get the value from the properties.
742  GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
743  __ ret(0);
744}
745
746
747bool StubCompiler::GenerateLoadCallback(JSObject* object,
748                                        JSObject* holder,
749                                        Register receiver,
750                                        Register name_reg,
751                                        Register scratch1,
752                                        Register scratch2,
753                                        AccessorInfo* callback,
754                                        String* name,
755                                        Label* miss,
756                                        Failure** failure) {
757  // Check that the receiver isn't a smi.
758  __ test(receiver, Immediate(kSmiTagMask));
759  __ j(zero, miss, not_taken);
760
761  // Check that the maps haven't changed.
762  Register reg =
763      CheckPrototypes(object, receiver, holder,
764                      scratch1, scratch2, name, miss);
765
766  Handle<AccessorInfo> callback_handle(callback);
767
768  Register other = reg.is(scratch1) ? scratch2 : scratch1;
769  __ EnterInternalFrame();
770  __ PushHandleScope(other);
771  // Push the stack address where the list of arguments ends
772  __ mov(other, esp);
773  __ sub(Operand(other), Immediate(2 * kPointerSize));
774  __ push(other);
775  __ push(receiver);  // receiver
776  __ push(reg);  // holder
777  __ mov(other, Immediate(callback_handle));
778  __ push(other);
779  __ push(FieldOperand(other, AccessorInfo::kDataOffset));  // data
780  __ push(name_reg);  // name
781  // Save a pointer to where we pushed the arguments pointer.
782  // This will be passed as the const Arguments& to the C++ callback.
783  __ mov(eax, esp);
784  __ add(Operand(eax), Immediate(5 * kPointerSize));
785  __ mov(ebx, esp);
786
787  // Do call through the api.
788  ASSERT_EQ(6, ApiGetterEntryStub::kStackSpace);
789  Address getter_address = v8::ToCData<Address>(callback->getter());
790  ApiFunction fun(getter_address);
791  ApiGetterEntryStub stub(callback_handle, &fun);
792  // Emitting a stub call may try to allocate (if the code is not
793  // already generated).  Do not allow the assembler to perform a
794  // garbage collection but instead return the allocation failure
795  // object.
796  Object* result = masm()->TryCallStub(&stub);
797  if (result->IsFailure()) {
798    *failure = Failure::cast(result);
799    return false;
800  }
801
802  // We need to avoid using eax since that now holds the result.
803  Register tmp = other.is(eax) ? reg : other;
804  // Emitting PopHandleScope may try to allocate.  Do not allow the
805  // assembler to perform a garbage collection but instead return a
806  // failure object.
807  result = masm()->TryPopHandleScope(eax, tmp);
808  if (result->IsFailure()) {
809    *failure = Failure::cast(result);
810    return false;
811  }
812  __ LeaveInternalFrame();
813
814  __ ret(0);
815  return true;
816}
817
818
819void StubCompiler::GenerateLoadConstant(JSObject* object,
820                                        JSObject* holder,
821                                        Register receiver,
822                                        Register scratch1,
823                                        Register scratch2,
824                                        Object* value,
825                                        String* name,
826                                        Label* miss) {
827  // Check that the receiver isn't a smi.
828  __ test(receiver, Immediate(kSmiTagMask));
829  __ j(zero, miss, not_taken);
830
831  // Check that the maps haven't changed.
832  Register reg =
833      CheckPrototypes(object, receiver, holder,
834                      scratch1, scratch2, name, miss);
835
836  // Return the constant value.
837  __ mov(eax, Handle<Object>(value));
838  __ ret(0);
839}
840
841
842void StubCompiler::GenerateLoadInterceptor(JSObject* object,
843                                           JSObject* holder,
844                                           LookupResult* lookup,
845                                           Register receiver,
846                                           Register name_reg,
847                                           Register scratch1,
848                                           Register scratch2,
849                                           String* name,
850                                           Label* miss) {
851  LoadInterceptorCompiler compiler(name_reg);
852  CompileLoadInterceptor(&compiler,
853                         this,
854                         masm(),
855                         object,
856                         holder,
857                         name,
858                         lookup,
859                         receiver,
860                         scratch1,
861                         scratch2,
862                         miss);
863}
864
865
866// TODO(1241006): Avoid having lazy compile stubs specialized by the
867// number of arguments. It is not needed anymore.
868Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
869  // Enter an internal frame.
870  __ EnterInternalFrame();
871
872  // Push a copy of the function onto the stack.
873  __ push(edi);
874
875  __ push(edi);  // function is also the parameter to the runtime call
876  __ CallRuntime(Runtime::kLazyCompile, 1);
877  __ pop(edi);
878
879  // Tear down temporary frame.
880  __ LeaveInternalFrame();
881
882  // Do a tail-call of the compiled function.
883  __ lea(ecx, FieldOperand(eax, Code::kHeaderSize));
884  __ jmp(Operand(ecx));
885
886  return GetCodeWithFlags(flags, "LazyCompileStub");
887}
888
889
890Object* CallStubCompiler::CompileCallField(Object* object,
891                                           JSObject* holder,
892                                           int index,
893                                           String* name) {
894  // ----------- S t a t e -------------
895  //  -- ecx                 : name
896  //  -- esp[0]              : return address
897  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
898  //  -- ...
899  //  -- esp[(argc + 1) * 4] : receiver
900  // -----------------------------------
901  Label miss;
902
903  // Get the receiver from the stack.
904  const int argc = arguments().immediate();
905  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
906
907  // Check that the receiver isn't a smi.
908  __ test(edx, Immediate(kSmiTagMask));
909  __ j(zero, &miss, not_taken);
910
911  // Do the right check and compute the holder register.
912  Register reg =
913      CheckPrototypes(JSObject::cast(object), edx, holder,
914                      ebx, eax, name, &miss);
915
916  GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
917
918  // Check that the function really is a function.
919  __ test(edi, Immediate(kSmiTagMask));
920  __ j(zero, &miss, not_taken);
921  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
922  __ j(not_equal, &miss, not_taken);
923
924  // Patch the receiver on the stack with the global proxy if
925  // necessary.
926  if (object->IsGlobalObject()) {
927    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
928    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
929  }
930
931  // Invoke the function.
932  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
933
934  // Handle call cache miss.
935  __ bind(&miss);
936  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
937  __ jmp(ic, RelocInfo::CODE_TARGET);
938
939  // Return the generated code.
940  return GetCode(FIELD, name);
941}
942
943
944Object* CallStubCompiler::CompileCallConstant(Object* object,
945                                              JSObject* holder,
946                                              JSFunction* function,
947                                              String* name,
948                                              CheckType check) {
949  // ----------- S t a t e -------------
950  //  -- ecx                 : name
951  //  -- esp[0]              : return address
952  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
953  //  -- ...
954  //  -- esp[(argc + 1) * 4] : receiver
955  // -----------------------------------
956  Label miss;
957
958  // Get the receiver from the stack.
959  const int argc = arguments().immediate();
960  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
961
962  // Check that the receiver isn't a smi.
963  if (check != NUMBER_CHECK) {
964    __ test(edx, Immediate(kSmiTagMask));
965    __ j(zero, &miss, not_taken);
966  }
967
968  // Make sure that it's okay not to patch the on stack receiver
969  // unless we're doing a receiver map check.
970  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
971
972  switch (check) {
973    case RECEIVER_MAP_CHECK:
974      // Check that the maps haven't changed.
975      CheckPrototypes(JSObject::cast(object), edx, holder,
976                      ebx, eax, name, &miss);
977
978      // Patch the receiver on the stack with the global proxy if
979      // necessary.
980      if (object->IsGlobalObject()) {
981        __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
982        __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
983      }
984      break;
985
986    case STRING_CHECK:
987      if (!function->IsBuiltin()) {
988        // Calling non-builtins with a value as receiver requires boxing.
989        __ jmp(&miss);
990      } else {
991        // Check that the object is a string or a symbol.
992        __ mov(eax, FieldOperand(edx, HeapObject::kMapOffset));
993        __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
994        __ cmp(eax, FIRST_NONSTRING_TYPE);
995        __ j(above_equal, &miss, not_taken);
996        // Check that the maps starting from the prototype haven't changed.
997        GenerateLoadGlobalFunctionPrototype(masm(),
998                                            Context::STRING_FUNCTION_INDEX,
999                                            eax);
1000        CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
1001                        ebx, edx, name, &miss);
1002      }
1003      break;
1004
1005    case NUMBER_CHECK: {
1006      if (!function->IsBuiltin()) {
1007        // Calling non-builtins with a value as receiver requires boxing.
1008        __ jmp(&miss);
1009      } else {
1010        Label fast;
1011        // Check that the object is a smi or a heap number.
1012        __ test(edx, Immediate(kSmiTagMask));
1013        __ j(zero, &fast, taken);
1014        __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
1015        __ j(not_equal, &miss, not_taken);
1016        __ bind(&fast);
1017        // Check that the maps starting from the prototype haven't changed.
1018        GenerateLoadGlobalFunctionPrototype(masm(),
1019                                            Context::NUMBER_FUNCTION_INDEX,
1020                                            eax);
1021        CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
1022                        ebx, edx, name, &miss);
1023      }
1024      break;
1025    }
1026
1027    case BOOLEAN_CHECK: {
1028      if (!function->IsBuiltin()) {
1029        // Calling non-builtins with a value as receiver requires boxing.
1030        __ jmp(&miss);
1031      } else {
1032        Label fast;
1033        // Check that the object is a boolean.
1034        __ cmp(edx, Factory::true_value());
1035        __ j(equal, &fast, taken);
1036        __ cmp(edx, Factory::false_value());
1037        __ j(not_equal, &miss, not_taken);
1038        __ bind(&fast);
1039        // Check that the maps starting from the prototype haven't changed.
1040        GenerateLoadGlobalFunctionPrototype(masm(),
1041                                            Context::BOOLEAN_FUNCTION_INDEX,
1042                                            eax);
1043        CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
1044                        ebx, edx, name, &miss);
1045      }
1046      break;
1047    }
1048
1049    case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
1050      CheckPrototypes(JSObject::cast(object), edx, holder,
1051                      ebx, eax, name, &miss);
1052      // Make sure object->HasFastElements().
1053      // Get the elements array of the object.
1054      __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
1055      // Check that the object is in fast mode (not dictionary).
1056      __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1057             Immediate(Factory::fixed_array_map()));
1058      __ j(not_equal, &miss, not_taken);
1059      break;
1060
1061    default:
1062      UNREACHABLE();
1063  }
1064
1065  // Get the function and setup the context.
1066  __ mov(edi, Immediate(Handle<JSFunction>(function)));
1067  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1068
1069  // Jump to the cached code (tail call).
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
1076  // Handle call cache miss.
1077  __ bind(&miss);
1078  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
1079  __ jmp(ic, RelocInfo::CODE_TARGET);
1080
1081  // Return the generated code.
1082  String* function_name = NULL;
1083  if (function->shared()->name()->IsString()) {
1084    function_name = String::cast(function->shared()->name());
1085  }
1086  return GetCode(CONSTANT_FUNCTION, function_name);
1087}
1088
1089
1090Object* CallStubCompiler::CompileCallInterceptor(Object* object,
1091                                                 JSObject* holder,
1092                                                 String* name) {
1093  // ----------- S t a t e -------------
1094  //  -- ecx                 : name
1095  //  -- esp[0]              : return address
1096  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1097  //  -- ...
1098  //  -- esp[(argc + 1) * 4] : receiver
1099  // -----------------------------------
1100  Label miss;
1101
1102  // Get the number of arguments.
1103  const int argc = arguments().immediate();
1104
1105  LookupResult lookup;
1106  LookupPostInterceptor(holder, name, &lookup);
1107
1108  // Get the receiver from the stack.
1109  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1110
1111  CallInterceptorCompiler compiler(arguments(), ecx);
1112  CompileLoadInterceptor(&compiler,
1113                         this,
1114                         masm(),
1115                         JSObject::cast(object),
1116                         holder,
1117                         name,
1118                         &lookup,
1119                         edx,
1120                         ebx,
1121                         edi,
1122                         &miss);
1123
1124  // Restore receiver.
1125  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1126
1127  // Check that the function really is a function.
1128  __ test(eax, Immediate(kSmiTagMask));
1129  __ j(zero, &miss, not_taken);
1130  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
1131  __ j(not_equal, &miss, not_taken);
1132
1133  // Patch the receiver on the stack with the global proxy if
1134  // necessary.
1135  if (object->IsGlobalObject()) {
1136    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1137    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1138  }
1139
1140  // Invoke the function.
1141  __ mov(edi, eax);
1142  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
1143
1144  // Handle load cache miss.
1145  __ bind(&miss);
1146  Handle<Code> ic = ComputeCallMiss(argc);
1147  __ jmp(ic, RelocInfo::CODE_TARGET);
1148
1149  // Return the generated code.
1150  return GetCode(INTERCEPTOR, name);
1151}
1152
1153
1154Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
1155                                            GlobalObject* holder,
1156                                            JSGlobalPropertyCell* cell,
1157                                            JSFunction* function,
1158                                            String* name) {
1159  // ----------- S t a t e -------------
1160  //  -- ecx                 : name
1161  //  -- esp[0]              : return address
1162  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1163  //  -- ...
1164  //  -- esp[(argc + 1) * 4] : receiver
1165  // -----------------------------------
1166  Label miss;
1167
1168  // Get the number of arguments.
1169  const int argc = arguments().immediate();
1170
1171  // Get the receiver from the stack.
1172  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1173
1174  // If the object is the holder then we know that it's a global
1175  // object which can only happen for contextual calls. In this case,
1176  // the receiver cannot be a smi.
1177  if (object != holder) {
1178    __ test(edx, Immediate(kSmiTagMask));
1179    __ j(zero, &miss, not_taken);
1180  }
1181
1182  // Check that the maps haven't changed.
1183  CheckPrototypes(object, edx, holder, ebx, eax, name, &miss);
1184
1185  // Get the value from the cell.
1186  __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1187  __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
1188
1189  // Check that the cell contains the same function.
1190  if (Heap::InNewSpace(function)) {
1191    // We can't embed a pointer to a function in new space so we have
1192    // to verify that the shared function info is unchanged. This has
1193    // the nice side effect that multiple closures based on the same
1194    // function can all use this call IC. Before we load through the
1195    // function, we have to verify that it still is a function.
1196    __ test(edi, Immediate(kSmiTagMask));
1197    __ j(zero, &miss, not_taken);
1198    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1199    __ j(not_equal, &miss, not_taken);
1200
1201    // Check the shared function info. Make sure it hasn't changed.
1202    __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
1203           Immediate(Handle<SharedFunctionInfo>(function->shared())));
1204    __ j(not_equal, &miss, not_taken);
1205  } else {
1206    __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function)));
1207    __ j(not_equal, &miss, not_taken);
1208  }
1209
1210  // Patch the receiver on the stack with the global proxy.
1211  if (object->IsGlobalObject()) {
1212    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1213    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1214  }
1215
1216  // Setup the context (function already in edi).
1217  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1218
1219  // Jump to the cached code (tail call).
1220  __ IncrementCounter(&Counters::call_global_inline, 1);
1221  ASSERT(function->is_compiled());
1222  Handle<Code> code(function->code());
1223  ParameterCount expected(function->shared()->formal_parameter_count());
1224  __ InvokeCode(code, expected, arguments(),
1225                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
1226
1227  // Handle call cache miss.
1228  __ bind(&miss);
1229  __ IncrementCounter(&Counters::call_global_inline_miss, 1);
1230  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
1231  __ jmp(ic, RelocInfo::CODE_TARGET);
1232
1233  // Return the generated code.
1234  return GetCode(NORMAL, name);
1235}
1236
1237
1238Object* StoreStubCompiler::CompileStoreField(JSObject* object,
1239                                             int index,
1240                                             Map* transition,
1241                                             String* name) {
1242  // ----------- S t a t e -------------
1243  //  -- eax    : value
1244  //  -- ecx    : name
1245  //  -- edx    : receiver
1246  //  -- esp[0] : return address
1247  // -----------------------------------
1248  Label miss;
1249
1250  // Generate store field code.  Trashes the name register.
1251  GenerateStoreField(masm(),
1252                     Builtins::StoreIC_ExtendStorage,
1253                     object,
1254                     index,
1255                     transition,
1256                     edx, ecx, ebx,
1257                     &miss);
1258
1259  // Handle store cache miss.
1260  __ bind(&miss);
1261  __ mov(ecx, Immediate(Handle<String>(name)));  // restore name
1262  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1263  __ jmp(ic, RelocInfo::CODE_TARGET);
1264
1265  // Return the generated code.
1266  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
1267}
1268
1269
1270Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
1271                                                AccessorInfo* callback,
1272                                                String* name) {
1273  // ----------- S t a t e -------------
1274  //  -- eax    : value
1275  //  -- ecx    : name
1276  //  -- edx    : receiver
1277  //  -- esp[0] : return address
1278  // -----------------------------------
1279  Label miss;
1280
1281  // Check that the object isn't a smi.
1282  __ test(edx, Immediate(kSmiTagMask));
1283  __ j(zero, &miss, not_taken);
1284
1285  // Check that the map of the object hasn't changed.
1286  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
1287         Immediate(Handle<Map>(object->map())));
1288  __ j(not_equal, &miss, not_taken);
1289
1290  // Perform global security token check if needed.
1291  if (object->IsJSGlobalProxy()) {
1292    __ CheckAccessGlobalProxy(edx, ebx, &miss);
1293  }
1294
1295  // Stub never generated for non-global objects that require access
1296  // checks.
1297  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
1298
1299  __ pop(ebx);  // remove the return address
1300  __ push(edx);  // receiver
1301  __ push(Immediate(Handle<AccessorInfo>(callback)));  // callback info
1302  __ push(ecx);  // name
1303  __ push(eax);  // value
1304  __ push(ebx);  // restore return address
1305
1306  // Do tail-call to the runtime system.
1307  ExternalReference store_callback_property =
1308      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
1309  __ TailCallRuntime(store_callback_property, 4, 1);
1310
1311  // Handle store cache miss.
1312  __ bind(&miss);
1313  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1314  __ jmp(ic, RelocInfo::CODE_TARGET);
1315
1316  // Return the generated code.
1317  return GetCode(CALLBACKS, name);
1318}
1319
1320
1321Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
1322                                                   String* name) {
1323  // ----------- S t a t e -------------
1324  //  -- eax    : value
1325  //  -- ecx    : name
1326  //  -- edx    : receiver
1327  //  -- esp[0] : return address
1328  // -----------------------------------
1329  Label miss;
1330
1331  // Check that the object isn't a smi.
1332  __ test(edx, Immediate(kSmiTagMask));
1333  __ j(zero, &miss, not_taken);
1334
1335  // Check that the map of the object hasn't changed.
1336  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
1337         Immediate(Handle<Map>(receiver->map())));
1338  __ j(not_equal, &miss, not_taken);
1339
1340  // Perform global security token check if needed.
1341  if (receiver->IsJSGlobalProxy()) {
1342    __ CheckAccessGlobalProxy(edx, ebx, &miss);
1343  }
1344
1345  // Stub never generated for non-global objects that require access
1346  // checks.
1347  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
1348
1349  __ pop(ebx);  // remove the return address
1350  __ push(edx);  // receiver
1351  __ push(ecx);  // name
1352  __ push(eax);  // value
1353  __ push(ebx);  // restore return address
1354
1355  // Do tail-call to the runtime system.
1356  ExternalReference store_ic_property =
1357      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
1358  __ TailCallRuntime(store_ic_property, 3, 1);
1359
1360  // Handle store cache miss.
1361  __ bind(&miss);
1362  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1363  __ jmp(ic, RelocInfo::CODE_TARGET);
1364
1365  // Return the generated code.
1366  return GetCode(INTERCEPTOR, name);
1367}
1368
1369
1370Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
1371                                              JSGlobalPropertyCell* cell,
1372                                              String* name) {
1373  // ----------- S t a t e -------------
1374  //  -- eax    : value
1375  //  -- ecx    : name
1376  //  -- edx    : receiver
1377  //  -- esp[0] : return address
1378  // -----------------------------------
1379  Label miss;
1380
1381  // Check that the map of the global has not changed.
1382  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
1383         Immediate(Handle<Map>(object->map())));
1384  __ j(not_equal, &miss, not_taken);
1385
1386  // Store the value in the cell.
1387  __ mov(ecx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1388  __ mov(FieldOperand(ecx, JSGlobalPropertyCell::kValueOffset), eax);
1389
1390  // Return the value (register eax).
1391  __ IncrementCounter(&Counters::named_store_global_inline, 1);
1392  __ ret(0);
1393
1394  // Handle store cache miss.
1395  __ bind(&miss);
1396  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
1397  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1398  __ jmp(ic, RelocInfo::CODE_TARGET);
1399
1400  // Return the generated code.
1401  return GetCode(NORMAL, name);
1402}
1403
1404
1405Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1406                                                  int index,
1407                                                  Map* transition,
1408                                                  String* name) {
1409  // ----------- S t a t e -------------
1410  //  -- eax    : value
1411  //  -- esp[0] : return address
1412  //  -- esp[4] : key
1413  //  -- esp[8] : receiver
1414  // -----------------------------------
1415  Label miss;
1416
1417  __ IncrementCounter(&Counters::keyed_store_field, 1);
1418
1419  // Get the name from the stack.
1420  __ mov(ecx, Operand(esp, 1 * kPointerSize));
1421  // Check that the name has not changed.
1422  __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
1423  __ j(not_equal, &miss, not_taken);
1424
1425  // Get the object from the stack.
1426  __ mov(ebx, Operand(esp, 2 * kPointerSize));
1427
1428  // Generate store field code.  Trashes the name register.
1429  GenerateStoreField(masm(),
1430                     Builtins::KeyedStoreIC_ExtendStorage,
1431                     object,
1432                     index,
1433                     transition,
1434                     ebx, ecx, edx,
1435                     &miss);
1436
1437  // Handle store cache miss.
1438  __ bind(&miss);
1439  __ DecrementCounter(&Counters::keyed_store_field, 1);
1440  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1441  __ jmp(ic, RelocInfo::CODE_TARGET);
1442
1443  // Return the generated code.
1444  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
1445}
1446
1447
1448
1449Object* LoadStubCompiler::CompileLoadField(JSObject* object,
1450                                           JSObject* holder,
1451                                           int index,
1452                                           String* name) {
1453  // ----------- S t a t e -------------
1454  //  -- ecx    : name
1455  //  -- esp[0] : return address
1456  //  -- esp[4] : receiver
1457  // -----------------------------------
1458  Label miss;
1459
1460  __ mov(eax, Operand(esp, kPointerSize));
1461  GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss);
1462  __ bind(&miss);
1463  GenerateLoadMiss(masm(), Code::LOAD_IC);
1464
1465  // Return the generated code.
1466  return GetCode(FIELD, name);
1467}
1468
1469
1470Object* LoadStubCompiler::CompileLoadCallback(String* name,
1471                                              JSObject* object,
1472                                              JSObject* holder,
1473                                              AccessorInfo* callback) {
1474  // ----------- S t a t e -------------
1475  //  -- ecx    : name
1476  //  -- esp[0] : return address
1477  //  -- esp[4] : receiver
1478  // -----------------------------------
1479  Label miss;
1480
1481  __ mov(eax, Operand(esp, kPointerSize));
1482  Failure* failure = Failure::InternalError();
1483  bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
1484                                      callback, name, &miss, &failure);
1485  if (!success) return failure;
1486
1487  __ bind(&miss);
1488  GenerateLoadMiss(masm(), Code::LOAD_IC);
1489
1490  // Return the generated code.
1491  return GetCode(CALLBACKS, name);
1492}
1493
1494
1495Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
1496                                              JSObject* holder,
1497                                              Object* value,
1498                                              String* name) {
1499  // ----------- S t a t e -------------
1500  //  -- ecx    : name
1501  //  -- esp[0] : return address
1502  //  -- esp[4] : receiver
1503  // -----------------------------------
1504  Label miss;
1505
1506  __ mov(eax, Operand(esp, kPointerSize));
1507  GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss);
1508  __ bind(&miss);
1509  GenerateLoadMiss(masm(), Code::LOAD_IC);
1510
1511  // Return the generated code.
1512  return GetCode(CONSTANT_FUNCTION, name);
1513}
1514
1515
1516Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1517                                                 JSObject* holder,
1518                                                 String* name) {
1519  // ----------- S t a t e -------------
1520  //  -- ecx    : name
1521  //  -- esp[0] : return address
1522  //  -- esp[4] : receiver
1523  // -----------------------------------
1524  Label miss;
1525
1526  LookupResult lookup;
1527  LookupPostInterceptor(holder, name, &lookup);
1528
1529  __ mov(eax, Operand(esp, kPointerSize));
1530  // TODO(368): Compile in the whole chain: all the interceptors in
1531  // prototypes and ultimate answer.
1532  GenerateLoadInterceptor(receiver,
1533                          holder,
1534                          &lookup,
1535                          eax,
1536                          ecx,
1537                          edx,
1538                          ebx,
1539                          name,
1540                          &miss);
1541
1542  __ bind(&miss);
1543  GenerateLoadMiss(masm(), Code::LOAD_IC);
1544
1545  // Return the generated code.
1546  return GetCode(INTERCEPTOR, name);
1547}
1548
1549
1550Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
1551                                            GlobalObject* holder,
1552                                            JSGlobalPropertyCell* cell,
1553                                            String* name,
1554                                            bool is_dont_delete) {
1555  // ----------- S t a t e -------------
1556  //  -- ecx    : name
1557  //  -- esp[0] : return address
1558  //  -- esp[4] : receiver
1559  // -----------------------------------
1560  Label miss;
1561
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
1566  // object which can only happen for contextual loads. In this case,
1567  // the receiver cannot be a smi.
1568  if (object != holder) {
1569    __ test(eax, Immediate(kSmiTagMask));
1570    __ j(zero, &miss, not_taken);
1571  }
1572
1573  // Check that the maps haven't changed.
1574  CheckPrototypes(object, eax, holder, ebx, edx, name, &miss);
1575
1576  // Get the value from the cell.
1577  __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1578  __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
1579
1580  // Check for deleted property if property can actually be deleted.
1581  if (!is_dont_delete) {
1582    __ cmp(eax, Factory::the_hole_value());
1583    __ j(equal, &miss, not_taken);
1584  } else if (FLAG_debug_code) {
1585    __ cmp(eax, Factory::the_hole_value());
1586    __ Check(not_equal, "DontDelete cells can't contain the hole");
1587  }
1588
1589  __ IncrementCounter(&Counters::named_load_global_inline, 1);
1590  __ ret(0);
1591
1592  __ bind(&miss);
1593  __ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
1594  GenerateLoadMiss(masm(), Code::LOAD_IC);
1595
1596  // Return the generated code.
1597  return GetCode(NORMAL, name);
1598}
1599
1600
1601Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
1602                                                JSObject* receiver,
1603                                                JSObject* holder,
1604                                                int index) {
1605  // ----------- S t a t e -------------
1606  //  -- esp[0] : return address
1607  //  -- esp[4] : name
1608  //  -- esp[8] : receiver
1609  // -----------------------------------
1610  Label miss;
1611
1612  __ mov(eax, Operand(esp, kPointerSize));
1613  __ mov(ecx, Operand(esp, 2 * kPointerSize));
1614  __ IncrementCounter(&Counters::keyed_load_field, 1);
1615
1616  // Check that the name has not changed.
1617  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1618  __ j(not_equal, &miss, not_taken);
1619
1620  GenerateLoadField(receiver, holder, ecx, ebx, edx, index, name, &miss);
1621
1622  __ bind(&miss);
1623  __ DecrementCounter(&Counters::keyed_load_field, 1);
1624  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1625
1626  // Return the generated code.
1627  return GetCode(FIELD, name);
1628}
1629
1630
1631Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1632                                                   JSObject* receiver,
1633                                                   JSObject* holder,
1634                                                   AccessorInfo* callback) {
1635  // ----------- S t a t e -------------
1636  //  -- esp[0] : return address
1637  //  -- esp[4] : name
1638  //  -- esp[8] : receiver
1639  // -----------------------------------
1640  Label miss;
1641
1642  __ mov(eax, Operand(esp, kPointerSize));
1643  __ mov(ecx, Operand(esp, 2 * kPointerSize));
1644  __ IncrementCounter(&Counters::keyed_load_callback, 1);
1645
1646  // Check that the name has not changed.
1647  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1648  __ j(not_equal, &miss, not_taken);
1649
1650  Failure* failure = Failure::InternalError();
1651  bool success = GenerateLoadCallback(receiver, holder, ecx, eax, ebx, edx,
1652                                      callback, name, &miss, &failure);
1653  if (!success) return failure;
1654
1655  __ bind(&miss);
1656  __ DecrementCounter(&Counters::keyed_load_callback, 1);
1657  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1658
1659  // Return the generated code.
1660  return GetCode(CALLBACKS, name);
1661}
1662
1663
1664Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1665                                                   JSObject* receiver,
1666                                                   JSObject* holder,
1667                                                   Object* value) {
1668  // ----------- S t a t e -------------
1669  //  -- esp[0] : return address
1670  //  -- esp[4] : name
1671  //  -- esp[8] : receiver
1672  // -----------------------------------
1673  Label miss;
1674
1675  __ mov(eax, Operand(esp, kPointerSize));
1676  __ mov(ecx, Operand(esp, 2 * kPointerSize));
1677  __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
1678
1679  // Check that the name has not changed.
1680  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1681  __ j(not_equal, &miss, not_taken);
1682
1683  GenerateLoadConstant(receiver, holder, ecx, ebx, edx,
1684                       value, name, &miss);
1685  __ bind(&miss);
1686  __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
1687  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1688
1689  // Return the generated code.
1690  return GetCode(CONSTANT_FUNCTION, name);
1691}
1692
1693
1694Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1695                                                      JSObject* holder,
1696                                                      String* name) {
1697  // ----------- S t a t e -------------
1698  //  -- esp[0] : return address
1699  //  -- esp[4] : name
1700  //  -- esp[8] : receiver
1701  // -----------------------------------
1702  Label miss;
1703
1704  __ mov(eax, Operand(esp, kPointerSize));
1705  __ mov(ecx, Operand(esp, 2 * kPointerSize));
1706  __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
1707
1708  // Check that the name has not changed.
1709  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1710  __ j(not_equal, &miss, not_taken);
1711
1712  LookupResult lookup;
1713  LookupPostInterceptor(holder, name, &lookup);
1714  GenerateLoadInterceptor(receiver,
1715                          holder,
1716                          &lookup,
1717                          ecx,
1718                          eax,
1719                          edx,
1720                          ebx,
1721                          name,
1722                          &miss);
1723  __ bind(&miss);
1724  __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
1725  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1726
1727  // Return the generated code.
1728  return GetCode(INTERCEPTOR, name);
1729}
1730
1731
1732
1733
1734Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
1735  // ----------- S t a t e -------------
1736  //  -- esp[0] : return address
1737  //  -- esp[4] : name
1738  //  -- esp[8] : receiver
1739  // -----------------------------------
1740  Label miss;
1741
1742  __ mov(eax, Operand(esp, kPointerSize));
1743  __ mov(ecx, Operand(esp, 2 * kPointerSize));
1744  __ IncrementCounter(&Counters::keyed_load_array_length, 1);
1745
1746  // Check that the name has not changed.
1747  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1748  __ j(not_equal, &miss, not_taken);
1749
1750  GenerateLoadArrayLength(masm(), ecx, edx, &miss);
1751  __ bind(&miss);
1752  __ DecrementCounter(&Counters::keyed_load_array_length, 1);
1753  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1754
1755  // Return the generated code.
1756  return GetCode(CALLBACKS, name);
1757}
1758
1759
1760Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
1761  // ----------- S t a t e -------------
1762  //  -- esp[0] : return address
1763  //  -- esp[4] : name
1764  //  -- esp[8] : receiver
1765  // -----------------------------------
1766  Label miss;
1767
1768  __ mov(eax, Operand(esp, kPointerSize));
1769  __ mov(ecx, Operand(esp, 2 * kPointerSize));
1770  __ IncrementCounter(&Counters::keyed_load_string_length, 1);
1771
1772  // Check that the name has not changed.
1773  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1774  __ j(not_equal, &miss, not_taken);
1775
1776  GenerateLoadStringLength(masm(), ecx, edx, &miss);
1777  __ bind(&miss);
1778  __ DecrementCounter(&Counters::keyed_load_string_length, 1);
1779  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1780
1781  // Return the generated code.
1782  return GetCode(CALLBACKS, name);
1783}
1784
1785
1786Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
1787  // ----------- S t a t e -------------
1788  //  -- esp[0] : return address
1789  //  -- esp[4] : name
1790  //  -- esp[8] : receiver
1791  // -----------------------------------
1792  Label miss;
1793
1794  __ mov(eax, Operand(esp, kPointerSize));
1795  __ mov(ecx, Operand(esp, 2 * kPointerSize));
1796  __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
1797
1798  // Check that the name has not changed.
1799  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1800  __ j(not_equal, &miss, not_taken);
1801
1802  GenerateLoadFunctionPrototype(masm(), ecx, edx, ebx, &miss);
1803  __ bind(&miss);
1804  __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
1805  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1806
1807  // Return the generated code.
1808  return GetCode(CALLBACKS, name);
1809}
1810
1811
1812// Specialized stub for constructing objects from functions which only have only
1813// simple assignments of the form this.x = ...; in their body.
1814Object* ConstructStubCompiler::CompileConstructStub(
1815    SharedFunctionInfo* shared) {
1816  // ----------- S t a t e -------------
1817  //  -- eax : argc
1818  //  -- edi : constructor
1819  //  -- esp[0] : return address
1820  //  -- esp[4] : last argument
1821  // -----------------------------------
1822  Label generic_stub_call;
1823#ifdef ENABLE_DEBUGGER_SUPPORT
1824  // Check to see whether there are any break points in the function code. If
1825  // there are jump to the generic constructor stub which calls the actual
1826  // code for the function thereby hitting the break points.
1827  __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1828  __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset));
1829  __ cmp(ebx, Factory::undefined_value());
1830  __ j(not_equal, &generic_stub_call, not_taken);
1831#endif
1832
1833  // Load the initial map and verify that it is in fact a map.
1834  __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1835  // Will both indicate a NULL and a Smi.
1836  __ test(ebx, Immediate(kSmiTagMask));
1837  __ j(zero, &generic_stub_call);
1838  __ CmpObjectType(ebx, MAP_TYPE, ecx);
1839  __ j(not_equal, &generic_stub_call);
1840
1841#ifdef DEBUG
1842  // Cannot construct functions this way.
1843  // edi: constructor
1844  // ebx: initial map
1845  __ CmpInstanceType(ebx, JS_FUNCTION_TYPE);
1846  __ Assert(not_equal, "Function constructed by construct stub.");
1847#endif
1848
1849  // Now allocate the JSObject on the heap by moving the new space allocation
1850  // top forward.
1851  // edi: constructor
1852  // ebx: initial map
1853  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
1854  __ shl(ecx, kPointerSizeLog2);
1855  __ AllocateInNewSpace(ecx,
1856                        edx,
1857                        ecx,
1858                        no_reg,
1859                        &generic_stub_call,
1860                        NO_ALLOCATION_FLAGS);
1861
1862  // Allocated the JSObject, now initialize the fields and add the heap tag.
1863  // ebx: initial map
1864  // edx: JSObject (untagged)
1865  __ mov(Operand(edx, JSObject::kMapOffset), ebx);
1866  __ mov(ebx, Factory::empty_fixed_array());
1867  __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx);
1868  __ mov(Operand(edx, JSObject::kElementsOffset), ebx);
1869
1870  // Push the allocated object to the stack. This is the object that will be
1871  // returned (after it is tagged).
1872  __ push(edx);
1873
1874  // eax: argc
1875  // edx: JSObject (untagged)
1876  // Load the address of the first in-object property into edx.
1877  __ lea(edx, Operand(edx, JSObject::kHeaderSize));
1878  // Calculate the location of the first argument. The stack contains the
1879  // allocated object and the return address on top of the argc arguments.
1880  __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize));
1881
1882  // Use edi for holding undefined which is used in several places below.
1883  __ mov(edi, Factory::undefined_value());
1884
1885  // eax: argc
1886  // ecx: first argument
1887  // edx: first in-object property of the JSObject
1888  // edi: undefined
1889  // Fill the initialized properties with a constant value or a passed argument
1890  // depending on the this.x = ...; assignment in the function.
1891  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
1892    if (shared->IsThisPropertyAssignmentArgument(i)) {
1893      // Check if the argument assigned to the property is actually passed.
1894      // If argument is not passed the property is set to undefined,
1895      // otherwise find it on the stack.
1896      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
1897      __ mov(ebx, edi);
1898      __ cmp(eax, arg_number);
1899      if (CpuFeatures::IsSupported(CMOV)) {
1900        CpuFeatures::Scope use_cmov(CMOV);
1901        __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize));
1902      } else {
1903        Label not_passed;
1904        __ j(below_equal, &not_passed);
1905        __ mov(ebx, Operand(ecx, arg_number * -kPointerSize));
1906        __ bind(&not_passed);
1907      }
1908      // Store value in the property.
1909      __ mov(Operand(edx, i * kPointerSize), ebx);
1910    } else {
1911      // Set the property to the constant value.
1912      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
1913      __ mov(Operand(edx, i * kPointerSize), Immediate(constant));
1914    }
1915  }
1916
1917  // Fill the unused in-object property fields with undefined.
1918  for (int i = shared->this_property_assignments_count();
1919       i < shared->CalculateInObjectProperties();
1920       i++) {
1921    __ mov(Operand(edx, i * kPointerSize), edi);
1922  }
1923
1924  // Move argc to ebx and retrieve and tag the JSObject to return.
1925  __ mov(ebx, eax);
1926  __ pop(eax);
1927  __ or_(Operand(eax), Immediate(kHeapObjectTag));
1928
1929  // Remove caller arguments and receiver from the stack and return.
1930  __ pop(ecx);
1931  __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize));
1932  __ push(ecx);
1933  __ IncrementCounter(&Counters::constructed_objects, 1);
1934  __ IncrementCounter(&Counters::constructed_objects_stub, 1);
1935  __ ret(0);
1936
1937  // Jump to the generic stub in case the specialized code cannot handle the
1938  // construction.
1939  __ bind(&generic_stub_call);
1940  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
1941  Handle<Code> generic_construct_stub(code);
1942  __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
1943
1944  // Return the generated code.
1945  return GetCode();
1946}
1947
1948
1949#undef __
1950
1951} }  // namespace v8::internal
1952