v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
stub-cache-ia32.cc
Go to the documentation of this file.
1 // Copyright 2012 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 #if defined(V8_TARGET_ARCH_IA32)
31 
32 #include "ic-inl.h"
33 #include "codegen.h"
34 #include "stub-cache.h"
35 
36 namespace v8 {
37 namespace internal {
38 
39 #define __ ACCESS_MASM(masm)
40 
41 
42 static void ProbeTable(Isolate* isolate,
43  MacroAssembler* masm,
45  StubCache::Table table,
46  Register name,
47  Register receiver,
48  // Number of the cache entry pointer-size scaled.
49  Register offset,
50  Register extra) {
51  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
52  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
53  ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
54 
55  Label miss;
56 
57  // Multiply by 3 because there are 3 fields per entry (name, code, map).
58  __ lea(offset, Operand(offset, offset, times_2, 0));
59 
60  if (extra.is_valid()) {
61  // Get the code entry from the cache.
62  __ mov(extra, Operand::StaticArray(offset, times_1, value_offset));
63 
64  // Check that the key in the entry matches the name.
65  __ cmp(name, Operand::StaticArray(offset, times_1, key_offset));
66  __ j(not_equal, &miss);
67 
68  // Check the map matches.
69  __ mov(offset, Operand::StaticArray(offset, times_1, map_offset));
70  __ cmp(offset, FieldOperand(receiver, HeapObject::kMapOffset));
71  __ j(not_equal, &miss);
72 
73  // Check that the flags match what we're looking for.
74  __ mov(offset, FieldOperand(extra, Code::kFlagsOffset));
75  __ and_(offset, ~Code::kFlagsNotUsedInLookup);
76  __ cmp(offset, flags);
77  __ j(not_equal, &miss);
78 
79 #ifdef DEBUG
80  if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
81  __ jmp(&miss);
82  } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
83  __ jmp(&miss);
84  }
85 #endif
86 
87  // Jump to the first instruction in the code stub.
88  __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
89  __ jmp(extra);
90 
91  __ bind(&miss);
92  } else {
93  // Save the offset on the stack.
94  __ push(offset);
95 
96  // Check that the key in the entry matches the name.
97  __ cmp(name, Operand::StaticArray(offset, times_1, key_offset));
98  __ j(not_equal, &miss);
99 
100  // Check the map matches.
101  __ mov(offset, Operand::StaticArray(offset, times_1, map_offset));
102  __ cmp(offset, FieldOperand(receiver, HeapObject::kMapOffset));
103  __ j(not_equal, &miss);
104 
105  // Restore offset register.
106  __ mov(offset, Operand(esp, 0));
107 
108  // Get the code entry from the cache.
109  __ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
110 
111  // Check that the flags match what we're looking for.
112  __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
113  __ and_(offset, ~Code::kFlagsNotUsedInLookup);
114  __ cmp(offset, flags);
115  __ j(not_equal, &miss);
116 
117 #ifdef DEBUG
118  if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
119  __ jmp(&miss);
120  } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
121  __ jmp(&miss);
122  }
123 #endif
124 
125  // Restore offset and re-load code entry from cache.
126  __ pop(offset);
127  __ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
128 
129  // Jump to the first instruction in the code stub.
130  __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
131  __ jmp(offset);
132 
133  // Pop at miss.
134  __ bind(&miss);
135  __ pop(offset);
136  }
137 }
138 
139 
140 // Helper function used to check that the dictionary doesn't contain
141 // the property. This function may return false negatives, so miss_label
142 // must always call a backup property check that is complete.
143 // This function is safe to call if the receiver has fast properties.
144 // Name must be a symbol and receiver must be a heap object.
145 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
146  Label* miss_label,
147  Register receiver,
148  Handle<String> name,
149  Register r0,
150  Register r1) {
151  ASSERT(name->IsSymbol());
152  Counters* counters = masm->isolate()->counters();
153  __ IncrementCounter(counters->negative_lookups(), 1);
154  __ IncrementCounter(counters->negative_lookups_miss(), 1);
155 
156  __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
157 
158  const int kInterceptorOrAccessCheckNeededMask =
160 
161  // Bail out if the receiver has a named interceptor or requires access checks.
163  kInterceptorOrAccessCheckNeededMask);
164  __ j(not_zero, miss_label);
165 
166  // Check that receiver is a JSObject.
167  __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE);
168  __ j(below, miss_label);
169 
170  // Load properties array.
171  Register properties = r0;
172  __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
173 
174  // Check that the properties array is a dictionary.
175  __ cmp(FieldOperand(properties, HeapObject::kMapOffset),
176  Immediate(masm->isolate()->factory()->hash_table_map()));
177  __ j(not_equal, miss_label);
178 
179  Label done;
181  miss_label,
182  &done,
183  properties,
184  name,
185  r1);
186  __ bind(&done);
187  __ DecrementCounter(counters->negative_lookups_miss(), 1);
188 }
189 
190 
191 void StubCache::GenerateProbe(MacroAssembler* masm,
192  Code::Flags flags,
193  Register receiver,
194  Register name,
195  Register scratch,
196  Register extra,
197  Register extra2,
198  Register extra3) {
199  Label miss;
200 
201  // Assert that code is valid. The multiplying code relies on the entry size
202  // being 12.
203  ASSERT(sizeof(Entry) == 12);
204 
205  // Assert the flags do not name a specific type.
206  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
207 
208  // Assert that there are no register conflicts.
209  ASSERT(!scratch.is(receiver));
210  ASSERT(!scratch.is(name));
211  ASSERT(!extra.is(receiver));
212  ASSERT(!extra.is(name));
213  ASSERT(!extra.is(scratch));
214 
215  // Assert scratch and extra registers are valid, and extra2/3 are unused.
216  ASSERT(!scratch.is(no_reg));
217  ASSERT(extra2.is(no_reg));
218  ASSERT(extra3.is(no_reg));
219 
220  Register offset = scratch;
221  scratch = no_reg;
222 
223  Counters* counters = masm->isolate()->counters();
224  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
225 
226  // Check that the receiver isn't a smi.
227  __ JumpIfSmi(receiver, &miss);
228 
229  // Get the map of the receiver and compute the hash.
230  __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
231  __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
232  __ xor_(offset, flags);
233  // We mask out the last two bits because they are not part of the hash and
234  // they are always 01 for maps. Also in the two 'and' instructions below.
235  __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
236  // ProbeTable expects the offset to be pointer scaled, which it is, because
237  // the heap object tag size is 2 and the pointer size log 2 is also 2.
239 
240  // Probe the primary table.
241  ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra);
242 
243  // Primary miss: Compute hash for secondary probe.
244  __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
245  __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
246  __ xor_(offset, flags);
247  __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
248  __ sub(offset, name);
249  __ add(offset, Immediate(flags));
250  __ and_(offset, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
251 
252  // Probe the secondary table.
253  ProbeTable(
254  isolate(), masm, flags, kSecondary, name, receiver, offset, extra);
255 
256  // Cache miss: Fall-through and let caller handle the miss by
257  // entering the runtime system.
258  __ bind(&miss);
259  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
260 }
261 
262 
263 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
264  int index,
265  Register prototype) {
266  __ LoadGlobalFunction(index, prototype);
267  __ LoadGlobalFunctionInitialMap(prototype, prototype);
268  // Load the prototype from the initial map.
269  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
270 }
271 
272 
273 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
274  MacroAssembler* masm,
275  int index,
276  Register prototype,
277  Label* miss) {
278  // Check we're still in the same context.
280  masm->isolate()->global());
281  __ j(not_equal, miss);
282  // Get the global function with the given index.
283  Handle<JSFunction> function(
284  JSFunction::cast(masm->isolate()->global_context()->get(index)));
285  // Load its initial map. The global functions all have initial maps.
286  __ Set(prototype, Immediate(Handle<Map>(function->initial_map())));
287  // Load the prototype from the initial map.
288  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
289 }
290 
291 
292 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
293  Register receiver,
294  Register scratch,
295  Label* miss_label) {
296  // Check that the receiver isn't a smi.
297  __ JumpIfSmi(receiver, miss_label);
298 
299  // Check that the object is a JS array.
300  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
301  __ j(not_equal, miss_label);
302 
303  // Load length directly from the JS array.
304  __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
305  __ ret(0);
306 }
307 
308 
309 // Generate code to check if an object is a string. If the object is
310 // a string, the map's instance type is left in the scratch register.
311 static void GenerateStringCheck(MacroAssembler* masm,
312  Register receiver,
313  Register scratch,
314  Label* smi,
315  Label* non_string_object) {
316  // Check that the object isn't a smi.
317  __ JumpIfSmi(receiver, smi);
318 
319  // Check that the object is a string.
320  __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
321  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
323  __ test(scratch, Immediate(kNotStringTag));
324  __ j(not_zero, non_string_object);
325 }
326 
327 
328 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
329  Register receiver,
330  Register scratch1,
331  Register scratch2,
332  Label* miss,
333  bool support_wrappers) {
334  Label check_wrapper;
335 
336  // Check if the object is a string leaving the instance type in the
337  // scratch register.
338  GenerateStringCheck(masm, receiver, scratch1, miss,
339  support_wrappers ? &check_wrapper : miss);
340 
341  // Load length from the string and convert to a smi.
342  __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
343  __ ret(0);
344 
345  if (support_wrappers) {
346  // Check if the object is a JSValue wrapper.
347  __ bind(&check_wrapper);
348  __ cmp(scratch1, JS_VALUE_TYPE);
349  __ j(not_equal, miss);
350 
351  // Check if the wrapped value is a string and load the length
352  // directly if it is.
353  __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
354  GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
355  __ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
356  __ ret(0);
357  }
358 }
359 
360 
361 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
362  Register receiver,
363  Register scratch1,
364  Register scratch2,
365  Label* miss_label) {
366  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
367  __ mov(eax, scratch1);
368  __ ret(0);
369 }
370 
371 
372 // Load a fast property out of a holder object (src). In-object properties
373 // are loaded directly otherwise the property is loaded from the properties
374 // fixed array.
375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
376  Register dst,
377  Register src,
378  Handle<JSObject> holder,
379  int index) {
380  // Adjust for the number of properties stored in the holder.
381  index -= holder->map()->inobject_properties();
382  if (index < 0) {
383  // Get the property straight out of the holder.
384  int offset = holder->map()->instance_size() + (index * kPointerSize);
385  __ mov(dst, FieldOperand(src, offset));
386  } else {
387  // Calculate the offset into the properties array.
388  int offset = index * kPointerSize + FixedArray::kHeaderSize;
390  __ mov(dst, FieldOperand(dst, offset));
391  }
392 }
393 
394 
395 static void PushInterceptorArguments(MacroAssembler* masm,
396  Register receiver,
397  Register holder,
398  Register name,
399  Handle<JSObject> holder_obj) {
400  __ push(name);
401  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
402  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
403  Register scratch = name;
404  __ mov(scratch, Immediate(interceptor));
405  __ push(scratch);
406  __ push(receiver);
407  __ push(holder);
409  __ push(Immediate(reinterpret_cast<int>(masm->isolate())));
410 }
411 
412 
413 static void CompileCallLoadPropertyWithInterceptor(
414  MacroAssembler* masm,
415  Register receiver,
416  Register holder,
417  Register name,
418  Handle<JSObject> holder_obj) {
419  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
420  __ CallExternalReference(
421  ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
422  masm->isolate()),
423  6);
424 }
425 
426 
427 // Number of pointers to be reserved on stack for fast API call.
428 static const int kFastApiCallArguments = 4;
429 
430 
431 // Reserves space for the extra arguments to API function in the
432 // caller's frame.
433 //
434 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
435 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
436  // ----------- S t a t e -------------
437  // -- esp[0] : return address
438  // -- esp[4] : last argument in the internal frame of the caller
439  // -----------------------------------
440  __ pop(scratch);
441  for (int i = 0; i < kFastApiCallArguments; i++) {
442  __ push(Immediate(Smi::FromInt(0)));
443  }
444  __ push(scratch);
445 }
446 
447 
448 // Undoes the effects of ReserveSpaceForFastApiCall.
449 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
450  // ----------- S t a t e -------------
451  // -- esp[0] : return address.
452  // -- esp[4] : last fast api call extra argument.
453  // -- ...
454  // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument.
455  // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal
456  // frame.
457  // -----------------------------------
458  __ pop(scratch);
459  __ add(esp, Immediate(kPointerSize * kFastApiCallArguments));
460  __ push(scratch);
461 }
462 
463 
464 // Generates call to API function.
465 static void GenerateFastApiCall(MacroAssembler* masm,
466  const CallOptimization& optimization,
467  int argc) {
468  // ----------- S t a t e -------------
469  // -- esp[0] : return address
470  // -- esp[4] : object passing the type check
471  // (last fast api call extra argument,
472  // set by CheckPrototypes)
473  // -- esp[8] : api function
474  // (first fast api call extra argument)
475  // -- esp[12] : api call data
476  // -- esp[16] : isolate
477  // -- esp[20] : last argument
478  // -- ...
479  // -- esp[(argc + 4) * 4] : first argument
480  // -- esp[(argc + 5) * 4] : receiver
481  // -----------------------------------
482  // Get the function and setup the context.
483  Handle<JSFunction> function = optimization.constant_function();
484  __ LoadHeapObject(edi, function);
486 
487  // Pass the additional arguments.
488  __ mov(Operand(esp, 2 * kPointerSize), edi);
489  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
490  Handle<Object> call_data(api_call_info->data());
491  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
492  __ mov(ecx, api_call_info);
494  __ mov(Operand(esp, 3 * kPointerSize), ebx);
495  } else {
496  __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data));
497  }
498  __ mov(Operand(esp, 4 * kPointerSize),
499  Immediate(reinterpret_cast<int>(masm->isolate())));
500 
501  // Prepare arguments.
502  __ lea(eax, Operand(esp, 4 * kPointerSize));
503 
504  const int kApiArgc = 1; // API function gets reference to the v8::Arguments.
505 
506  // Allocate the v8::Arguments structure in the arguments' space since
507  // it's not controlled by GC.
508  const int kApiStackSpace = 4;
509 
510  __ PrepareCallApiFunction(kApiArgc + kApiStackSpace);
511 
512  __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_.
513  __ add(eax, Immediate(argc * kPointerSize));
514  __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_.
515  __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_.
516  // v8::Arguments::is_construct_call_.
517  __ Set(ApiParameterOperand(4), Immediate(0));
518 
519  // v8::InvocationCallback's argument.
520  __ lea(eax, ApiParameterOperand(1));
521  __ mov(ApiParameterOperand(0), eax);
522 
523  // Function address is a foreign pointer outside V8's heap.
524  Address function_address = v8::ToCData<Address>(api_call_info->callback());
525  __ CallApiFunctionAndReturn(function_address,
526  argc + kFastApiCallArguments + 1);
527 }
528 
529 
530 class CallInterceptorCompiler BASE_EMBEDDED {
531  public:
532  CallInterceptorCompiler(StubCompiler* stub_compiler,
533  const ParameterCount& arguments,
534  Register name,
535  Code::ExtraICState extra_state)
536  : stub_compiler_(stub_compiler),
537  arguments_(arguments),
538  name_(name),
539  extra_state_(extra_state) {}
540 
541  void Compile(MacroAssembler* masm,
542  Handle<JSObject> object,
543  Handle<JSObject> holder,
544  Handle<String> name,
545  LookupResult* lookup,
546  Register receiver,
547  Register scratch1,
548  Register scratch2,
549  Register scratch3,
550  Label* miss) {
551  ASSERT(holder->HasNamedInterceptor());
552  ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
553 
554  // Check that the receiver isn't a smi.
555  __ JumpIfSmi(receiver, miss);
556 
557  CallOptimization optimization(lookup);
558  if (optimization.is_constant_call()) {
559  CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
560  holder, lookup, name, optimization, miss);
561  } else {
562  CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
563  name, holder, miss);
564  }
565  }
566 
567  private:
568  void CompileCacheable(MacroAssembler* masm,
569  Handle<JSObject> object,
570  Register receiver,
571  Register scratch1,
572  Register scratch2,
573  Register scratch3,
574  Handle<JSObject> interceptor_holder,
575  LookupResult* lookup,
576  Handle<String> name,
577  const CallOptimization& optimization,
578  Label* miss_label) {
579  ASSERT(optimization.is_constant_call());
580  ASSERT(!lookup->holder()->IsGlobalObject());
581 
582  int depth1 = kInvalidProtoDepth;
583  int depth2 = kInvalidProtoDepth;
584  bool can_do_fast_api_call = false;
585  if (optimization.is_simple_api_call() &&
586  !lookup->holder()->IsGlobalObject()) {
587  depth1 = optimization.GetPrototypeDepthOfExpectedType(
588  object, interceptor_holder);
589  if (depth1 == kInvalidProtoDepth) {
590  depth2 = optimization.GetPrototypeDepthOfExpectedType(
591  interceptor_holder, Handle<JSObject>(lookup->holder()));
592  }
593  can_do_fast_api_call =
594  depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
595  }
596 
597  Counters* counters = masm->isolate()->counters();
598  __ IncrementCounter(counters->call_const_interceptor(), 1);
599 
600  if (can_do_fast_api_call) {
601  __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
602  ReserveSpaceForFastApiCall(masm, scratch1);
603  }
604 
605  // Check that the maps from receiver to interceptor's holder
606  // haven't changed and thus we can invoke interceptor.
607  Label miss_cleanup;
608  Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
609  Register holder =
610  stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
611  scratch1, scratch2, scratch3,
612  name, depth1, miss);
613 
614  // Invoke an interceptor and if it provides a value,
615  // branch to |regular_invoke|.
616  Label regular_invoke;
617  LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
618  &regular_invoke);
619 
620  // Interceptor returned nothing for this property. Try to use cached
621  // constant function.
622 
623  // Check that the maps from interceptor's holder to constant function's
624  // holder haven't changed and thus we can use cached constant function.
625  if (*interceptor_holder != lookup->holder()) {
626  stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
627  Handle<JSObject>(lookup->holder()),
628  scratch1, scratch2, scratch3,
629  name, depth2, miss);
630  } else {
631  // CheckPrototypes has a side effect of fetching a 'holder'
632  // for API (object which is instanceof for the signature). It's
633  // safe to omit it here, as if present, it should be fetched
634  // by the previous CheckPrototypes.
635  ASSERT(depth2 == kInvalidProtoDepth);
636  }
637 
638  // Invoke function.
639  if (can_do_fast_api_call) {
640  GenerateFastApiCall(masm, optimization, arguments_.immediate());
641  } else {
642  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
644  : CALL_AS_METHOD;
645  __ InvokeFunction(optimization.constant_function(), arguments_,
646  JUMP_FUNCTION, NullCallWrapper(), call_kind);
647  }
648 
649  // Deferred code for fast API call case---clean preallocated space.
650  if (can_do_fast_api_call) {
651  __ bind(&miss_cleanup);
652  FreeSpaceForFastApiCall(masm, scratch1);
653  __ jmp(miss_label);
654  }
655 
656  // Invoke a regular function.
657  __ bind(&regular_invoke);
658  if (can_do_fast_api_call) {
659  FreeSpaceForFastApiCall(masm, scratch1);
660  }
661  }
662 
663  void CompileRegular(MacroAssembler* masm,
664  Handle<JSObject> object,
665  Register receiver,
666  Register scratch1,
667  Register scratch2,
668  Register scratch3,
669  Handle<String> name,
670  Handle<JSObject> interceptor_holder,
671  Label* miss_label) {
672  Register holder =
673  stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
674  scratch1, scratch2, scratch3,
675  name, miss_label);
676 
677  FrameScope scope(masm, StackFrame::INTERNAL);
678  // Save the name_ register across the call.
679  __ push(name_);
680 
681  PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
682 
683  __ CallExternalReference(
684  ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
685  masm->isolate()),
686  6);
687 
688  // Restore the name_ register.
689  __ pop(name_);
690 
691  // Leave the internal frame.
692  }
693 
694  void LoadWithInterceptor(MacroAssembler* masm,
695  Register receiver,
696  Register holder,
697  Handle<JSObject> holder_obj,
698  Label* interceptor_succeeded) {
699  {
700  FrameScope scope(masm, StackFrame::INTERNAL);
701  __ push(holder); // Save the holder.
702  __ push(name_); // Save the name.
703 
704  CompileCallLoadPropertyWithInterceptor(masm,
705  receiver,
706  holder,
707  name_,
708  holder_obj);
709 
710  __ pop(name_); // Restore the name.
711  __ pop(receiver); // Restore the holder.
712  // Leave the internal frame.
713  }
714 
715  __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
716  __ j(not_equal, interceptor_succeeded);
717  }
718 
719  StubCompiler* stub_compiler_;
720  const ParameterCount& arguments_;
721  Register name_;
722  Code::ExtraICState extra_state_;
723 };
724 
725 
726 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
727  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
728  Handle<Code> code = (kind == Code::LOAD_IC)
729  ? masm->isolate()->builtins()->LoadIC_Miss()
730  : masm->isolate()->builtins()->KeyedLoadIC_Miss();
731  __ jmp(code, RelocInfo::CODE_TARGET);
732 }
733 
734 
735 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
736  Handle<Code> code =
737  masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
738  __ jmp(code, RelocInfo::CODE_TARGET);
739 }
740 
741 
742 // Both name_reg and receiver_reg are preserved on jumps to miss_label,
743 // but may be destroyed if store is successful.
744 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
745  Handle<JSObject> object,
746  int index,
747  Handle<Map> transition,
748  Handle<String> name,
749  Register receiver_reg,
750  Register name_reg,
751  Register scratch1,
752  Register scratch2,
753  Label* miss_label) {
754  LookupResult lookup(masm->isolate());
755  object->Lookup(*name, &lookup);
756  if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
757  // In sloppy mode, we could just return the value and be done. However, we
758  // might be in strict mode, where we have to throw. Since we cannot tell,
759  // go into slow case unconditionally.
760  __ jmp(miss_label);
761  return;
762  }
763 
764  // Check that the map of the object hasn't changed.
765  CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
767  __ CheckMap(receiver_reg, Handle<Map>(object->map()),
768  miss_label, DO_SMI_CHECK, mode);
769 
770  // Perform global security token check if needed.
771  if (object->IsJSGlobalProxy()) {
772  __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
773  }
774 
775  // Check that we are allowed to write this.
776  if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
777  JSObject* holder;
778  if (lookup.IsFound()) {
779  holder = lookup.holder();
780  } else {
781  // Find the top object.
782  holder = *object;
783  do {
784  holder = JSObject::cast(holder->GetPrototype());
785  } while (holder->GetPrototype()->IsJSObject());
786  }
787  // We need an extra register, push
788  __ push(name_reg);
789  Label miss_pop, done_check;
790  CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
791  scratch1, scratch2, name, &miss_pop);
792  __ jmp(&done_check);
793  __ bind(&miss_pop);
794  __ pop(name_reg);
795  __ jmp(miss_label);
796  __ bind(&done_check);
797  __ pop(name_reg);
798  }
799 
800  // Stub never generated for non-global objects that require access
801  // checks.
802  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
803 
804  // Perform map transition for the receiver if necessary.
805  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
806  // The properties must be extended before we can store the value.
807  // We jump to a runtime call that extends the properties array.
808  __ pop(scratch1); // Return address.
809  __ push(receiver_reg);
810  __ push(Immediate(transition));
811  __ push(eax);
812  __ push(scratch1);
813  __ TailCallExternalReference(
814  ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
815  masm->isolate()),
816  3,
817  1);
818  return;
819  }
820 
821  if (!transition.is_null()) {
822  // Update the map of the object.
823  __ mov(scratch1, Immediate(transition));
824  __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
825 
826  // Update the write barrier for the map field and pass the now unused
827  // name_reg as scratch register.
828  __ RecordWriteField(receiver_reg,
830  scratch1,
831  name_reg,
835  }
836 
837  // Adjust for the number of properties stored in the object. Even in the
838  // face of a transition we can use the old map here because the size of the
839  // object and the number of in-object properties is not going to change.
840  index -= object->map()->inobject_properties();
841 
842  if (index < 0) {
843  // Set the property straight into the object.
844  int offset = object->map()->instance_size() + (index * kPointerSize);
845  __ mov(FieldOperand(receiver_reg, offset), eax);
846 
847  // Update the write barrier for the array address.
848  // Pass the value being stored in the now unused name_reg.
849  __ mov(name_reg, eax);
850  __ RecordWriteField(receiver_reg,
851  offset,
852  name_reg,
853  scratch1,
855  } else {
856  // Write to the properties array.
857  int offset = index * kPointerSize + FixedArray::kHeaderSize;
858  // Get the properties array (optimistically).
859  __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
860  __ mov(FieldOperand(scratch1, offset), eax);
861 
862  // Update the write barrier for the array address.
863  // Pass the value being stored in the now unused name_reg.
864  __ mov(name_reg, eax);
865  __ RecordWriteField(scratch1,
866  offset,
867  name_reg,
868  receiver_reg,
870  }
871 
872  // Return the value (register eax).
873  __ ret(0);
874 }
875 
876 
877 // Generate code to check that a global property cell is empty. Create
878 // the property cell at compilation time if no cell exists for the
879 // property.
880 static void GenerateCheckPropertyCell(MacroAssembler* masm,
881  Handle<GlobalObject> global,
882  Handle<String> name,
883  Register scratch,
884  Label* miss) {
885  Handle<JSGlobalPropertyCell> cell =
886  GlobalObject::EnsurePropertyCell(global, name);
887  ASSERT(cell->value()->IsTheHole());
888  Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value();
889  if (Serializer::enabled()) {
890  __ mov(scratch, Immediate(cell));
892  Immediate(the_hole));
893  } else {
894  __ cmp(Operand::Cell(cell), Immediate(the_hole));
895  }
896  __ j(not_equal, miss);
897 }
898 
899 
900 // Calls GenerateCheckPropertyCell for each global object in the prototype chain
901 // from object to (but not including) holder.
902 static void GenerateCheckPropertyCells(MacroAssembler* masm,
903  Handle<JSObject> object,
904  Handle<JSObject> holder,
905  Handle<String> name,
906  Register scratch,
907  Label* miss) {
908  Handle<JSObject> current = object;
909  while (!current.is_identical_to(holder)) {
910  if (current->IsGlobalObject()) {
911  GenerateCheckPropertyCell(masm,
912  Handle<GlobalObject>::cast(current),
913  name,
914  scratch,
915  miss);
916  }
917  current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
918  }
919 }
920 
921 #undef __
922 #define __ ACCESS_MASM(masm())
923 
924 
925 Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
926  Register object_reg,
927  Handle<JSObject> holder,
928  Register holder_reg,
929  Register scratch1,
930  Register scratch2,
931  Handle<String> name,
932  int save_at_depth,
933  Label* miss) {
934  // Make sure there's no overlap between holder and object registers.
935  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
936  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
937  && !scratch2.is(scratch1));
938 
939  // Keep track of the current object in register reg.
940  Register reg = object_reg;
941  Handle<JSObject> current = object;
942  int depth = 0;
943 
944  if (save_at_depth == depth) {
945  __ mov(Operand(esp, kPointerSize), reg);
946  }
947 
948  // Traverse the prototype chain and check the maps in the prototype chain for
949  // fast and global objects or do negative lookup for normal objects.
950  while (!current.is_identical_to(holder)) {
951  ++depth;
952 
953  // Only global objects and objects that do not require access
954  // checks are allowed in stubs.
955  ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
956 
957  Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
958  if (!current->HasFastProperties() &&
959  !current->IsJSGlobalObject() &&
960  !current->IsJSGlobalProxy()) {
961  if (!name->IsSymbol()) {
962  name = factory()->LookupSymbol(name);
963  }
964  ASSERT(current->property_dictionary()->FindEntry(*name) ==
966 
967  GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
968  scratch1, scratch2);
969 
970  __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
971  reg = holder_reg; // From now on the object will be in holder_reg.
972  __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
973  } else {
974  bool in_new_space = heap()->InNewSpace(*prototype);
975  Handle<Map> current_map(current->map());
976  if (in_new_space) {
977  // Save the map in scratch1 for later.
978  __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
979  }
980  __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK,
982 
983  // Check access rights to the global object. This has to happen after
984  // the map check so that we know that the object is actually a global
985  // object.
986  if (current->IsJSGlobalProxy()) {
987  __ CheckAccessGlobalProxy(reg, scratch2, miss);
988  }
989  reg = holder_reg; // From now on the object will be in holder_reg.
990 
991  if (in_new_space) {
992  // The prototype is in new space; we cannot store a reference to it
993  // in the code. Load it from the map.
994  __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
995  } else {
996  // The prototype is in old space; load it directly.
997  __ mov(reg, prototype);
998  }
999  }
1000 
1001  if (save_at_depth == depth) {
1002  __ mov(Operand(esp, kPointerSize), reg);
1003  }
1004 
1005  // Go to the next object in the prototype chain.
1006  current = prototype;
1007  }
1008  ASSERT(current.is_identical_to(holder));
1009 
1010  // Log the check depth.
1011  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1012 
1013  // Check the holder map.
1014  __ CheckMap(reg, Handle<Map>(holder->map()),
1016 
1017  // Perform security check for access to the global object.
1018  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
1019  if (holder->IsJSGlobalProxy()) {
1020  __ CheckAccessGlobalProxy(reg, scratch1, miss);
1021  }
1022 
1023  // If we've skipped any global objects, it's not enough to verify that
1024  // their maps haven't changed. We also need to check that the property
1025  // cell for the property is still empty.
1026  GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1027 
1028  // Return the register containing the holder.
1029  return reg;
1030 }
1031 
1032 
1033 void StubCompiler::GenerateLoadField(Handle<JSObject> object,
1034  Handle<JSObject> holder,
1035  Register receiver,
1036  Register scratch1,
1037  Register scratch2,
1038  Register scratch3,
1039  int index,
1040  Handle<String> name,
1041  Label* miss) {
1042  // Check that the receiver isn't a smi.
1043  __ JumpIfSmi(receiver, miss);
1044 
1045  // Check the prototype chain.
1046  Register reg = CheckPrototypes(
1047  object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1048 
1049  // Get the value from the properties.
1050  GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
1051  __ ret(0);
1052 }
1053 
1054 
1055 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
1056  Handle<JSObject> holder,
1057  Register receiver,
1058  Register name_reg,
1059  Register scratch1,
1060  Register scratch2,
1061  Register scratch3,
1062  Handle<AccessorInfo> callback,
1063  Handle<String> name,
1064  Label* miss) {
1065  // Check that the receiver isn't a smi.
1066  __ JumpIfSmi(receiver, miss);
1067 
1068  // Check that the maps haven't changed.
1069  Register reg = CheckPrototypes(object, receiver, holder, scratch1,
1070  scratch2, scratch3, name, miss);
1071 
1072  // Insert additional parameters into the stack frame above return address.
1073  ASSERT(!scratch3.is(reg));
1074  __ pop(scratch3); // Get return address to place it below.
1075 
1076  __ push(receiver); // receiver
1077  __ mov(scratch2, esp);
1078  ASSERT(!scratch2.is(reg));
1079  __ push(reg); // holder
1080  // Push data from AccessorInfo.
1081  if (isolate()->heap()->InNewSpace(callback->data())) {
1082  __ mov(scratch1, Immediate(callback));
1083  __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));
1084  } else {
1085  __ push(Immediate(Handle<Object>(callback->data())));
1086  }
1087  __ push(Immediate(reinterpret_cast<int>(isolate())));
1088 
1089  // Save a pointer to where we pushed the arguments pointer.
1090  // This will be passed as the const AccessorInfo& to the C++ callback.
1091  __ push(scratch2);
1092 
1093  __ push(name_reg); // name
1094  __ mov(ebx, esp); // esp points to reference to name (handler).
1095 
1096  __ push(scratch3); // Restore return address.
1097 
1098  // 4 elements array for v8::Arguments::values_, handler for name and pointer
1099  // to the values (it considered as smi in GC).
1100  const int kStackSpace = 6;
1101  const int kApiArgc = 2;
1102 
1103  __ PrepareCallApiFunction(kApiArgc);
1104  __ mov(ApiParameterOperand(0), ebx); // name.
1105  __ add(ebx, Immediate(kPointerSize));
1106  __ mov(ApiParameterOperand(1), ebx); // arguments pointer.
1107 
1108  // Emitting a stub call may try to allocate (if the code is not
1109  // already generated). Do not allow the assembler to perform a
1110  // garbage collection but instead return the allocation failure
1111  // object.
1112  Address getter_address = v8::ToCData<Address>(callback->getter());
1113  __ CallApiFunctionAndReturn(getter_address, kStackSpace);
1114 }
1115 
1116 
1117 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
1118  Handle<JSObject> holder,
1119  Register receiver,
1120  Register scratch1,
1121  Register scratch2,
1122  Register scratch3,
1123  Handle<JSFunction> value,
1124  Handle<String> name,
1125  Label* miss) {
1126  // Check that the receiver isn't a smi.
1127  __ JumpIfSmi(receiver, miss);
1128 
1129  // Check that the maps haven't changed.
1130  CheckPrototypes(
1131  object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1132 
1133  // Return the constant value.
1134  __ LoadHeapObject(eax, value);
1135  __ ret(0);
1136 }
1137 
1138 
1139 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
1140  Handle<JSObject> interceptor_holder,
1141  LookupResult* lookup,
1142  Register receiver,
1143  Register name_reg,
1144  Register scratch1,
1145  Register scratch2,
1146  Register scratch3,
1147  Handle<String> name,
1148  Label* miss) {
1149  ASSERT(interceptor_holder->HasNamedInterceptor());
1150  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1151 
1152  // Check that the receiver isn't a smi.
1153  __ JumpIfSmi(receiver, miss);
1154 
1155  // So far the most popular follow ups for interceptor loads are FIELD
1156  // and CALLBACKS, so inline only them, other cases may be added
1157  // later.
1158  bool compile_followup_inline = false;
1159  if (lookup->IsFound() && lookup->IsCacheable()) {
1160  if (lookup->type() == FIELD) {
1161  compile_followup_inline = true;
1162  } else if (lookup->type() == CALLBACKS &&
1163  lookup->GetCallbackObject()->IsAccessorInfo()) {
1164  AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1165  compile_followup_inline = callback->getter() != NULL &&
1166  callback->IsCompatibleReceiver(*object);
1167  }
1168  }
1169 
1170  if (compile_followup_inline) {
1171  // Compile the interceptor call, followed by inline code to load the
1172  // property from further up the prototype chain if the call fails.
1173  // Check that the maps haven't changed.
1174  Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
1175  scratch1, scratch2, scratch3,
1176  name, miss);
1177  ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1178 
1179  // Preserve the receiver register explicitly whenever it is different from
1180  // the holder and it is needed should the interceptor return without any
1181  // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1182  // the FIELD case might cause a miss during the prototype check.
1183  bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
1184  bool must_preserve_receiver_reg = !receiver.is(holder_reg) &&
1185  (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1186 
1187  // Save necessary data before invoking an interceptor.
1188  // Requires a frame to make GC aware of pushed pointers.
1189  {
1190  FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1191 
1192  if (must_preserve_receiver_reg) {
1193  __ push(receiver);
1194  }
1195  __ push(holder_reg);
1196  __ push(name_reg);
1197 
1198  // Invoke an interceptor. Note: map checks from receiver to
1199  // interceptor's holder has been compiled before (see a caller
1200  // of this method.)
1201  CompileCallLoadPropertyWithInterceptor(masm(),
1202  receiver,
1203  holder_reg,
1204  name_reg,
1205  interceptor_holder);
1206 
1207  // Check if interceptor provided a value for property. If it's
1208  // the case, return immediately.
1209  Label interceptor_failed;
1210  __ cmp(eax, factory()->no_interceptor_result_sentinel());
1211  __ j(equal, &interceptor_failed);
1212  frame_scope.GenerateLeaveFrame();
1213  __ ret(0);
1214 
1215  // Clobber registers when generating debug-code to provoke errors.
1216  __ bind(&interceptor_failed);
1217  if (FLAG_debug_code) {
1218  __ mov(receiver, Immediate(BitCast<int32_t>(kZapValue)));
1219  __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue)));
1220  __ mov(name_reg, Immediate(BitCast<int32_t>(kZapValue)));
1221  }
1222 
1223  __ pop(name_reg);
1224  __ pop(holder_reg);
1225  if (must_preserve_receiver_reg) {
1226  __ pop(receiver);
1227  }
1228 
1229  // Leave the internal frame.
1230  }
1231 
1232  // Check that the maps from interceptor's holder to lookup's holder
1233  // haven't changed. And load lookup's holder into holder_reg.
1234  if (must_perfrom_prototype_check) {
1235  holder_reg = CheckPrototypes(interceptor_holder,
1236  holder_reg,
1237  Handle<JSObject>(lookup->holder()),
1238  scratch1,
1239  scratch2,
1240  scratch3,
1241  name,
1242  miss);
1243  }
1244 
1245  if (lookup->type() == FIELD) {
1246  // We found FIELD property in prototype chain of interceptor's holder.
1247  // Retrieve a field from field's holder.
1248  GenerateFastPropertyLoad(masm(), eax, holder_reg,
1249  Handle<JSObject>(lookup->holder()),
1250  lookup->GetFieldIndex());
1251  __ ret(0);
1252  } else {
1253  // We found CALLBACKS property in prototype chain of interceptor's
1254  // holder.
1255  ASSERT(lookup->type() == CALLBACKS);
1256  Handle<AccessorInfo> callback(
1257  AccessorInfo::cast(lookup->GetCallbackObject()));
1258  ASSERT(callback->getter() != NULL);
1259 
1260  // Tail call to runtime.
1261  // Important invariant in CALLBACKS case: the code above must be
1262  // structured to never clobber |receiver| register.
1263  __ pop(scratch2); // return address
1264  __ push(receiver);
1265  __ push(holder_reg);
1266  __ mov(holder_reg, Immediate(callback));
1267  __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
1268  __ push(Immediate(reinterpret_cast<int>(isolate())));
1269  __ push(holder_reg);
1270  __ push(name_reg);
1271  __ push(scratch2); // restore return address
1272 
1273  ExternalReference ref =
1274  ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
1275  masm()->isolate());
1276  __ TailCallExternalReference(ref, 6, 1);
1277  }
1278  } else { // !compile_followup_inline
1279  // Call the runtime system to load the interceptor.
1280  // Check that the maps haven't changed.
1281  Register holder_reg =
1282  CheckPrototypes(object, receiver, interceptor_holder,
1283  scratch1, scratch2, scratch3, name, miss);
1284  __ pop(scratch2); // save old return address
1285  PushInterceptorArguments(masm(), receiver, holder_reg,
1286  name_reg, interceptor_holder);
1287  __ push(scratch2); // restore old return address
1288 
1289  ExternalReference ref =
1290  ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1291  isolate());
1292  __ TailCallExternalReference(ref, 6, 1);
1293  }
1294 }
1295 
1296 
1297 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
1298  if (kind_ == Code::KEYED_CALL_IC) {
1299  __ cmp(ecx, Immediate(name));
1300  __ j(not_equal, miss);
1301  }
1302 }
1303 
1304 
1305 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
1306  Handle<JSObject> holder,
1307  Handle<String> name,
1308  Label* miss) {
1309  ASSERT(holder->IsGlobalObject());
1310 
1311  // Get the number of arguments.
1312  const int argc = arguments().immediate();
1313 
1314  // Get the receiver from the stack.
1315  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1316 
1317 
1318  // Check that the maps haven't changed.
1319  __ JumpIfSmi(edx, miss);
1320  CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss);
1321 }
1322 
1323 
1324 void CallStubCompiler::GenerateLoadFunctionFromCell(
1325  Handle<JSGlobalPropertyCell> cell,
1326  Handle<JSFunction> function,
1327  Label* miss) {
1328  // Get the value from the cell.
1329  if (Serializer::enabled()) {
1330  __ mov(edi, Immediate(cell));
1332  } else {
1333  __ mov(edi, Operand::Cell(cell));
1334  }
1335 
1336  // Check that the cell contains the same function.
1337  if (isolate()->heap()->InNewSpace(*function)) {
1338  // We can't embed a pointer to a function in new space so we have
1339  // to verify that the shared function info is unchanged. This has
1340  // the nice side effect that multiple closures based on the same
1341  // function can all use this call IC. Before we load through the
1342  // function, we have to verify that it still is a function.
1343  __ JumpIfSmi(edi, miss);
1344  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1345  __ j(not_equal, miss);
1346 
1347  // Check the shared function info. Make sure it hasn't changed.
1349  Immediate(Handle<SharedFunctionInfo>(function->shared())));
1350  } else {
1351  __ cmp(edi, Immediate(function));
1352  }
1353  __ j(not_equal, miss);
1354 }
1355 
1356 
1357 void CallStubCompiler::GenerateMissBranch() {
1358  Handle<Code> code =
1359  isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1360  kind_,
1361  extra_state_);
1362  __ jmp(code, RelocInfo::CODE_TARGET);
1363 }
1364 
1365 
1366 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1367  Handle<JSObject> holder,
1368  int index,
1369  Handle<String> name) {
1370  // ----------- S t a t e -------------
1371  // -- ecx : name
1372  // -- esp[0] : return address
1373  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1374  // -- ...
1375  // -- esp[(argc + 1) * 4] : receiver
1376  // -----------------------------------
1377  Label miss;
1378 
1379  GenerateNameCheck(name, &miss);
1380 
1381  // Get the receiver from the stack.
1382  const int argc = arguments().immediate();
1383  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1384 
1385  // Check that the receiver isn't a smi.
1386  __ JumpIfSmi(edx, &miss);
1387 
1388  // Do the right check and compute the holder register.
1389  Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi,
1390  name, &miss);
1391 
1392  GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
1393 
1394  // Check that the function really is a function.
1395  __ JumpIfSmi(edi, &miss);
1396  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1397  __ j(not_equal, &miss);
1398 
1399  // Patch the receiver on the stack with the global proxy if
1400  // necessary.
1401  if (object->IsGlobalObject()) {
1403  __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1404  }
1405 
1406  // Invoke the function.
1407  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1409  : CALL_AS_METHOD;
1410  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
1411  NullCallWrapper(), call_kind);
1412 
1413  // Handle call cache miss.
1414  __ bind(&miss);
1415  GenerateMissBranch();
1416 
1417  // Return the generated code.
1418  return GetCode(FIELD, name);
1419 }
1420 
1421 
1422 Handle<Code> CallStubCompiler::CompileArrayPushCall(
1423  Handle<Object> object,
1424  Handle<JSObject> holder,
1425  Handle<JSGlobalPropertyCell> cell,
1426  Handle<JSFunction> function,
1427  Handle<String> name) {
1428  // ----------- S t a t e -------------
1429  // -- ecx : name
1430  // -- esp[0] : return address
1431  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1432  // -- ...
1433  // -- esp[(argc + 1) * 4] : receiver
1434  // -----------------------------------
1435 
1436  // If object is not an array, bail out to regular call.
1437  if (!object->IsJSArray() || !cell.is_null()) {
1438  return Handle<Code>::null();
1439  }
1440 
1441  Label miss;
1442 
1443  GenerateNameCheck(name, &miss);
1444 
1445  // Get the receiver from the stack.
1446  const int argc = arguments().immediate();
1447  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1448 
1449  // Check that the receiver isn't a smi.
1450  __ JumpIfSmi(edx, &miss);
1451 
1452  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1453  name, &miss);
1454 
1455  if (argc == 0) {
1456  // Noop, return the length.
1458  __ ret((argc + 1) * kPointerSize);
1459  } else {
1460  Label call_builtin;
1461 
1462  if (argc == 1) { // Otherwise fall through to call builtin.
1463  Label attempt_to_grow_elements, with_write_barrier;
1464 
1465  // Get the elements array of the object.
1467 
1468  // Check that the elements are in fast mode and writable.
1470  Immediate(factory()->fixed_array_map()));
1471  __ j(not_equal, &call_builtin);
1472 
1473  // Get the array's length into eax and calculate new length.
1475  STATIC_ASSERT(kSmiTagSize == 1);
1476  STATIC_ASSERT(kSmiTag == 0);
1477  __ add(eax, Immediate(Smi::FromInt(argc)));
1478 
1479  // Get the elements' length into ecx.
1481 
1482  // Check if we could survive without allocation.
1483  __ cmp(eax, ecx);
1484  __ j(greater, &attempt_to_grow_elements);
1485 
1486  // Check if value is a smi.
1487  __ mov(ecx, Operand(esp, argc * kPointerSize));
1488  __ JumpIfNotSmi(ecx, &with_write_barrier);
1489 
1490  // Save new length.
1492 
1493  // Store the value.
1494  __ mov(FieldOperand(edi,
1495  eax,
1497  FixedArray::kHeaderSize - argc * kPointerSize),
1498  ecx);
1499 
1500  __ ret((argc + 1) * kPointerSize);
1501 
1502  __ bind(&with_write_barrier);
1503 
1505 
1506  if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
1507  Label fast_object, not_fast_object;
1508  __ CheckFastObjectElements(ebx, &not_fast_object, Label::kNear);
1509  __ jmp(&fast_object);
1510  // In case of fast smi-only, convert to fast object, otherwise bail out.
1511  __ bind(&not_fast_object);
1512  __ CheckFastSmiElements(ebx, &call_builtin);
1513  // edi: elements array
1514  // edx: receiver
1515  // ebx: map
1516  Label try_holey_map;
1517  __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
1518  FAST_ELEMENTS,
1519  ebx,
1520  edi,
1521  &try_holey_map);
1522 
1525  // Restore edi.
1527  __ jmp(&fast_object);
1528 
1529  __ bind(&try_holey_map);
1530  __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1532  ebx,
1533  edi,
1534  &call_builtin);
1537  // Restore edi.
1539  __ bind(&fast_object);
1540  } else {
1541  __ CheckFastObjectElements(ebx, &call_builtin);
1542  }
1543 
1544  // Save new length.
1546 
1547  // Store the value.
1548  __ lea(edx, FieldOperand(edi,
1550  FixedArray::kHeaderSize - argc * kPointerSize));
1551  __ mov(Operand(edx, 0), ecx);
1552 
1553  __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1554  OMIT_SMI_CHECK);
1555 
1556  __ ret((argc + 1) * kPointerSize);
1557 
1558  __ bind(&attempt_to_grow_elements);
1559  if (!FLAG_inline_new) {
1560  __ jmp(&call_builtin);
1561  }
1562 
1563  __ mov(ebx, Operand(esp, argc * kPointerSize));
1564  // Growing elements that are SMI-only requires special handling in case
1565  // the new element is non-Smi. For now, delegate to the builtin.
1566  Label no_fast_elements_check;
1567  __ JumpIfSmi(ebx, &no_fast_elements_check);
1569  __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar);
1570  __ bind(&no_fast_elements_check);
1571 
1572  // We could be lucky and the elements array could be at the top of
1573  // new-space. In this case we can just grow it in place by moving the
1574  // allocation pointer up.
1575 
1576  ExternalReference new_space_allocation_top =
1577  ExternalReference::new_space_allocation_top_address(isolate());
1578  ExternalReference new_space_allocation_limit =
1579  ExternalReference::new_space_allocation_limit_address(isolate());
1580 
1581  const int kAllocationDelta = 4;
1582  // Load top.
1583  __ mov(ecx, Operand::StaticVariable(new_space_allocation_top));
1584 
1585  // Check if it's the end of elements.
1586  __ lea(edx, FieldOperand(edi,
1588  FixedArray::kHeaderSize - argc * kPointerSize));
1589  __ cmp(edx, ecx);
1590  __ j(not_equal, &call_builtin);
1591  __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
1592  __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
1593  __ j(above, &call_builtin);
1594 
1595  // We fit and could grow elements.
1596  __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
1597 
1598  // Push the argument...
1599  __ mov(Operand(edx, 0), ebx);
1600  // ... and fill the rest with holes.
1601  for (int i = 1; i < kAllocationDelta; i++) {
1602  __ mov(Operand(edx, i * kPointerSize),
1603  Immediate(factory()->the_hole_value()));
1604  }
1605 
1606  // We know the elements array is in new space so we don't need the
1607  // remembered set, but we just pushed a value onto it so we may have to
1608  // tell the incremental marker to rescan the object that we just grew. We
1609  // don't need to worry about the holes because they are in old space and
1610  // already marked black.
1611  __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1612 
1613  // Restore receiver to edx as finish sequence assumes it's here.
1614  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1615 
1616  // Increment element's and array's sizes.
1618  Immediate(Smi::FromInt(kAllocationDelta)));
1619 
1620  // NOTE: This only happen in new-space, where we don't
1621  // care about the black-byte-count on pages. Otherwise we should
1622  // update that too if the object is black.
1623 
1625 
1626  __ ret((argc + 1) * kPointerSize);
1627  }
1628 
1629  __ bind(&call_builtin);
1630  __ TailCallExternalReference(
1631  ExternalReference(Builtins::c_ArrayPush, isolate()),
1632  argc + 1,
1633  1);
1634  }
1635 
1636  __ bind(&miss);
1637  GenerateMissBranch();
1638 
1639  // Return the generated code.
1640  return GetCode(function);
1641 }
1642 
1643 
1644 Handle<Code> CallStubCompiler::CompileArrayPopCall(
1645  Handle<Object> object,
1646  Handle<JSObject> holder,
1647  Handle<JSGlobalPropertyCell> cell,
1648  Handle<JSFunction> function,
1649  Handle<String> name) {
1650  // ----------- S t a t e -------------
1651  // -- ecx : name
1652  // -- esp[0] : return address
1653  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1654  // -- ...
1655  // -- esp[(argc + 1) * 4] : receiver
1656  // -----------------------------------
1657 
1658  // If object is not an array, bail out to regular call.
1659  if (!object->IsJSArray() || !cell.is_null()) {
1660  return Handle<Code>::null();
1661  }
1662 
1663  Label miss, return_undefined, call_builtin;
1664 
1665  GenerateNameCheck(name, &miss);
1666 
1667  // Get the receiver from the stack.
1668  const int argc = arguments().immediate();
1669  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1670 
1671  // Check that the receiver isn't a smi.
1672  __ JumpIfSmi(edx, &miss);
1673  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1674  name, &miss);
1675 
1676  // Get the elements array of the object.
1678 
1679  // Check that the elements are in fast mode and writable.
1681  Immediate(factory()->fixed_array_map()));
1682  __ j(not_equal, &call_builtin);
1683 
1684  // Get the array's length into ecx and calculate new length.
1686  __ sub(ecx, Immediate(Smi::FromInt(1)));
1687  __ j(negative, &return_undefined);
1688 
1689  // Get the last element.
1690  STATIC_ASSERT(kSmiTagSize == 1);
1691  STATIC_ASSERT(kSmiTag == 0);
1692  __ mov(eax, FieldOperand(ebx,
1694  FixedArray::kHeaderSize));
1695  __ cmp(eax, Immediate(factory()->the_hole_value()));
1696  __ j(equal, &call_builtin);
1697 
1698  // Set the array's length.
1700 
1701  // Fill with the hole.
1702  __ mov(FieldOperand(ebx,
1704  FixedArray::kHeaderSize),
1705  Immediate(factory()->the_hole_value()));
1706  __ ret((argc + 1) * kPointerSize);
1707 
1708  __ bind(&return_undefined);
1709  __ mov(eax, Immediate(factory()->undefined_value()));
1710  __ ret((argc + 1) * kPointerSize);
1711 
1712  __ bind(&call_builtin);
1713  __ TailCallExternalReference(
1714  ExternalReference(Builtins::c_ArrayPop, isolate()),
1715  argc + 1,
1716  1);
1717 
1718  __ bind(&miss);
1719  GenerateMissBranch();
1720 
1721  // Return the generated code.
1722  return GetCode(function);
1723 }
1724 
1725 
1726 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
1727  Handle<Object> object,
1728  Handle<JSObject> holder,
1729  Handle<JSGlobalPropertyCell> cell,
1730  Handle<JSFunction> function,
1731  Handle<String> name) {
1732  // ----------- S t a t e -------------
1733  // -- ecx : function name
1734  // -- esp[0] : return address
1735  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1736  // -- ...
1737  // -- esp[(argc + 1) * 4] : receiver
1738  // -----------------------------------
1739 
1740  // If object is not a string, bail out to regular call.
1741  if (!object->IsString() || !cell.is_null()) {
1742  return Handle<Code>::null();
1743  }
1744 
1745  const int argc = arguments().immediate();
1746 
1747  Label miss;
1748  Label name_miss;
1749  Label index_out_of_range;
1750  Label* index_out_of_range_label = &index_out_of_range;
1751 
1752  if (kind_ == Code::CALL_IC &&
1753  (CallICBase::StringStubState::decode(extra_state_) ==
1755  index_out_of_range_label = &miss;
1756  }
1757 
1758  GenerateNameCheck(name, &name_miss);
1759 
1760  // Check that the maps starting from the prototype haven't changed.
1761  GenerateDirectLoadGlobalFunctionPrototype(masm(),
1763  eax,
1764  &miss);
1765  ASSERT(!object.is_identical_to(holder));
1766  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
1767  eax, holder, ebx, edx, edi, name, &miss);
1768 
1769  Register receiver = ebx;
1770  Register index = edi;
1771  Register result = eax;
1772  __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
1773  if (argc > 0) {
1774  __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
1775  } else {
1776  __ Set(index, Immediate(factory()->undefined_value()));
1777  }
1778 
1779  StringCharCodeAtGenerator generator(receiver,
1780  index,
1781  result,
1782  &miss, // When not a string.
1783  &miss, // When not a number.
1784  index_out_of_range_label,
1786  generator.GenerateFast(masm());
1787  __ ret((argc + 1) * kPointerSize);
1788 
1789  StubRuntimeCallHelper call_helper;
1790  generator.GenerateSlow(masm(), call_helper);
1791 
1792  if (index_out_of_range.is_linked()) {
1793  __ bind(&index_out_of_range);
1794  __ Set(eax, Immediate(factory()->nan_value()));
1795  __ ret((argc + 1) * kPointerSize);
1796  }
1797 
1798  __ bind(&miss);
1799  // Restore function name in ecx.
1800  __ Set(ecx, Immediate(name));
1801  __ bind(&name_miss);
1802  GenerateMissBranch();
1803 
1804  // Return the generated code.
1805  return GetCode(function);
1806 }
1807 
1808 
1809 Handle<Code> CallStubCompiler::CompileStringCharAtCall(
1810  Handle<Object> object,
1811  Handle<JSObject> holder,
1812  Handle<JSGlobalPropertyCell> cell,
1813  Handle<JSFunction> function,
1814  Handle<String> name) {
1815  // ----------- S t a t e -------------
1816  // -- ecx : function name
1817  // -- esp[0] : return address
1818  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1819  // -- ...
1820  // -- esp[(argc + 1) * 4] : receiver
1821  // -----------------------------------
1822 
1823  // If object is not a string, bail out to regular call.
1824  if (!object->IsString() || !cell.is_null()) {
1825  return Handle<Code>::null();
1826  }
1827 
1828  const int argc = arguments().immediate();
1829 
1830  Label miss;
1831  Label name_miss;
1832  Label index_out_of_range;
1833  Label* index_out_of_range_label = &index_out_of_range;
1834 
1835  if (kind_ == Code::CALL_IC &&
1836  (CallICBase::StringStubState::decode(extra_state_) ==
1838  index_out_of_range_label = &miss;
1839  }
1840 
1841  GenerateNameCheck(name, &name_miss);
1842 
1843  // Check that the maps starting from the prototype haven't changed.
1844  GenerateDirectLoadGlobalFunctionPrototype(masm(),
1846  eax,
1847  &miss);
1848  ASSERT(!object.is_identical_to(holder));
1849  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
1850  eax, holder, ebx, edx, edi, name, &miss);
1851 
1852  Register receiver = eax;
1853  Register index = edi;
1854  Register scratch = edx;
1855  Register result = eax;
1856  __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
1857  if (argc > 0) {
1858  __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
1859  } else {
1860  __ Set(index, Immediate(factory()->undefined_value()));
1861  }
1862 
1863  StringCharAtGenerator generator(receiver,
1864  index,
1865  scratch,
1866  result,
1867  &miss, // When not a string.
1868  &miss, // When not a number.
1869  index_out_of_range_label,
1871  generator.GenerateFast(masm());
1872  __ ret((argc + 1) * kPointerSize);
1873 
1874  StubRuntimeCallHelper call_helper;
1875  generator.GenerateSlow(masm(), call_helper);
1876 
1877  if (index_out_of_range.is_linked()) {
1878  __ bind(&index_out_of_range);
1879  __ Set(eax, Immediate(factory()->empty_string()));
1880  __ ret((argc + 1) * kPointerSize);
1881  }
1882 
1883  __ bind(&miss);
1884  // Restore function name in ecx.
1885  __ Set(ecx, Immediate(name));
1886  __ bind(&name_miss);
1887  GenerateMissBranch();
1888 
1889  // Return the generated code.
1890  return GetCode(function);
1891 }
1892 
1893 
1894 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
1895  Handle<Object> object,
1896  Handle<JSObject> holder,
1897  Handle<JSGlobalPropertyCell> cell,
1898  Handle<JSFunction> function,
1899  Handle<String> name) {
1900  // ----------- S t a t e -------------
1901  // -- ecx : function name
1902  // -- esp[0] : return address
1903  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1904  // -- ...
1905  // -- esp[(argc + 1) * 4] : receiver
1906  // -----------------------------------
1907 
1908  const int argc = arguments().immediate();
1909 
1910  // If the object is not a JSObject or we got an unexpected number of
1911  // arguments, bail out to the regular call.
1912  if (!object->IsJSObject() || argc != 1) {
1913  return Handle<Code>::null();
1914  }
1915 
1916  Label miss;
1917  GenerateNameCheck(name, &miss);
1918 
1919  if (cell.is_null()) {
1920  __ mov(edx, Operand(esp, 2 * kPointerSize));
1921  STATIC_ASSERT(kSmiTag == 0);
1922  __ JumpIfSmi(edx, &miss);
1923  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1924  name, &miss);
1925  } else {
1926  ASSERT(cell->value() == *function);
1927  GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
1928  &miss);
1929  GenerateLoadFunctionFromCell(cell, function, &miss);
1930  }
1931 
1932  // Load the char code argument.
1933  Register code = ebx;
1934  __ mov(code, Operand(esp, 1 * kPointerSize));
1935 
1936  // Check the code is a smi.
1937  Label slow;
1938  STATIC_ASSERT(kSmiTag == 0);
1939  __ JumpIfNotSmi(code, &slow);
1940 
1941  // Convert the smi code to uint16.
1942  __ and_(code, Immediate(Smi::FromInt(0xffff)));
1943 
1944  StringCharFromCodeGenerator generator(code, eax);
1945  generator.GenerateFast(masm());
1946  __ ret(2 * kPointerSize);
1947 
1948  StubRuntimeCallHelper call_helper;
1949  generator.GenerateSlow(masm(), call_helper);
1950 
1951  // Tail call the full function. We do not have to patch the receiver
1952  // because the function makes no use of it.
1953  __ bind(&slow);
1954  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1956  : CALL_AS_METHOD;
1957  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1958  NullCallWrapper(), call_kind);
1959 
1960  __ bind(&miss);
1961  // ecx: function name.
1962  GenerateMissBranch();
1963 
1964  // Return the generated code.
1965  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
1966 }
1967 
1968 
1969 Handle<Code> CallStubCompiler::CompileMathFloorCall(
1970  Handle<Object> object,
1971  Handle<JSObject> holder,
1972  Handle<JSGlobalPropertyCell> cell,
1973  Handle<JSFunction> function,
1974  Handle<String> name) {
1975  // ----------- S t a t e -------------
1976  // -- ecx : name
1977  // -- esp[0] : return address
1978  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1979  // -- ...
1980  // -- esp[(argc + 1) * 4] : receiver
1981  // -----------------------------------
1982 
1984  return Handle<Code>::null();
1985  }
1986 
1987  CpuFeatures::Scope use_sse2(SSE2);
1988 
1989  const int argc = arguments().immediate();
1990 
1991  // If the object is not a JSObject or we got an unexpected number of
1992  // arguments, bail out to the regular call.
1993  if (!object->IsJSObject() || argc != 1) {
1994  return Handle<Code>::null();
1995  }
1996 
1997  Label miss;
1998  GenerateNameCheck(name, &miss);
1999 
2000  if (cell.is_null()) {
2001  __ mov(edx, Operand(esp, 2 * kPointerSize));
2002 
2003  STATIC_ASSERT(kSmiTag == 0);
2004  __ JumpIfSmi(edx, &miss);
2005 
2006  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
2007  name, &miss);
2008  } else {
2009  ASSERT(cell->value() == *function);
2010  GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2011  &miss);
2012  GenerateLoadFunctionFromCell(cell, function, &miss);
2013  }
2014 
2015  // Load the (only) argument into eax.
2016  __ mov(eax, Operand(esp, 1 * kPointerSize));
2017 
2018  // Check if the argument is a smi.
2019  Label smi;
2020  STATIC_ASSERT(kSmiTag == 0);
2021  __ JumpIfSmi(eax, &smi);
2022 
2023  // Check if the argument is a heap number and load its value into xmm0.
2024  Label slow;
2025  __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2027 
2028  // Check if the argument is strictly positive. Note this also
2029  // discards NaN.
2030  __ xorpd(xmm1, xmm1);
2031  __ ucomisd(xmm0, xmm1);
2032  __ j(below_equal, &slow);
2033 
2034  // Do a truncating conversion.
2035  __ cvttsd2si(eax, Operand(xmm0));
2036 
2037  // Check if the result fits into a smi. Note this also checks for
2038  // 0x80000000 which signals a failed conversion.
2039  Label wont_fit_into_smi;
2040  __ test(eax, Immediate(0xc0000000));
2041  __ j(not_zero, &wont_fit_into_smi);
2042 
2043  // Smi tag and return.
2044  __ SmiTag(eax);
2045  __ bind(&smi);
2046  __ ret(2 * kPointerSize);
2047 
2048  // Check if the argument is < 2^kMantissaBits.
2049  Label already_round;
2050  __ bind(&wont_fit_into_smi);
2051  __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits);
2052  __ ucomisd(xmm0, xmm1);
2053  __ j(above_equal, &already_round);
2054 
2055  // Save a copy of the argument.
2056  __ movaps(xmm2, xmm0);
2057 
2058  // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
2059  __ addsd(xmm0, xmm1);
2060  __ subsd(xmm0, xmm1);
2061 
2062  // Compare the argument and the tentative result to get the right mask:
2063  // if xmm2 < xmm0:
2064  // xmm2 = 1...1
2065  // else:
2066  // xmm2 = 0...0
2067  __ cmpltsd(xmm2, xmm0);
2068 
2069  // Subtract 1 if the argument was less than the tentative result.
2070  __ LoadPowerOf2(xmm1, ebx, 0);
2071  __ andpd(xmm1, xmm2);
2072  __ subsd(xmm0, xmm1);
2073 
2074  // Return a new heap number.
2075  __ AllocateHeapNumber(eax, ebx, edx, &slow);
2077  __ ret(2 * kPointerSize);
2078 
2079  // Return the argument (when it's an already round heap number).
2080  __ bind(&already_round);
2081  __ mov(eax, Operand(esp, 1 * kPointerSize));
2082  __ ret(2 * kPointerSize);
2083 
2084  // Tail call the full function. We do not have to patch the receiver
2085  // because the function makes no use of it.
2086  __ bind(&slow);
2087  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2088  NullCallWrapper(), CALL_AS_METHOD);
2089 
2090  __ bind(&miss);
2091  // ecx: function name.
2092  GenerateMissBranch();
2093 
2094  // Return the generated code.
2095  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
2096 }
2097 
2098 
2099 Handle<Code> CallStubCompiler::CompileMathAbsCall(
2100  Handle<Object> object,
2101  Handle<JSObject> holder,
2102  Handle<JSGlobalPropertyCell> cell,
2103  Handle<JSFunction> function,
2104  Handle<String> name) {
2105  // ----------- S t a t e -------------
2106  // -- ecx : name
2107  // -- esp[0] : return address
2108  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2109  // -- ...
2110  // -- esp[(argc + 1) * 4] : receiver
2111  // -----------------------------------
2112 
2113  const int argc = arguments().immediate();
2114 
2115  // If the object is not a JSObject or we got an unexpected number of
2116  // arguments, bail out to the regular call.
2117  if (!object->IsJSObject() || argc != 1) {
2118  return Handle<Code>::null();
2119  }
2120 
2121  Label miss;
2122  GenerateNameCheck(name, &miss);
2123 
2124  if (cell.is_null()) {
2125  __ mov(edx, Operand(esp, 2 * kPointerSize));
2126 
2127  STATIC_ASSERT(kSmiTag == 0);
2128  __ JumpIfSmi(edx, &miss);
2129 
2130  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
2131  name, &miss);
2132  } else {
2133  ASSERT(cell->value() == *function);
2134  GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2135  &miss);
2136  GenerateLoadFunctionFromCell(cell, function, &miss);
2137  }
2138 
2139  // Load the (only) argument into eax.
2140  __ mov(eax, Operand(esp, 1 * kPointerSize));
2141 
2142  // Check if the argument is a smi.
2143  Label not_smi;
2144  STATIC_ASSERT(kSmiTag == 0);
2145  __ JumpIfNotSmi(eax, &not_smi);
2146 
2147  // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
2148  // otherwise.
2149  __ mov(ebx, eax);
2150  __ sar(ebx, kBitsPerInt - 1);
2151 
2152  // Do bitwise not or do nothing depending on ebx.
2153  __ xor_(eax, ebx);
2154 
2155  // Add 1 or do nothing depending on ebx.
2156  __ sub(eax, ebx);
2157 
2158  // If the result is still negative, go to the slow case.
2159  // This only happens for the most negative smi.
2160  Label slow;
2161  __ j(negative, &slow);
2162 
2163  // Smi case done.
2164  __ ret(2 * kPointerSize);
2165 
2166  // Check if the argument is a heap number and load its exponent and
2167  // sign into ebx.
2168  __ bind(&not_smi);
2169  __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2171 
2172  // Check the sign of the argument. If the argument is positive,
2173  // just return it.
2174  Label negative_sign;
2175  __ test(ebx, Immediate(HeapNumber::kSignMask));
2176  __ j(not_zero, &negative_sign);
2177  __ ret(2 * kPointerSize);
2178 
2179  // If the argument is negative, clear the sign, and return a new
2180  // number.
2181  __ bind(&negative_sign);
2182  __ and_(ebx, ~HeapNumber::kSignMask);
2184  __ AllocateHeapNumber(eax, edi, edx, &slow);
2187  __ ret(2 * kPointerSize);
2188 
2189  // Tail call the full function. We do not have to patch the receiver
2190  // because the function makes no use of it.
2191  __ bind(&slow);
2192  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2193  NullCallWrapper(), CALL_AS_METHOD);
2194 
2195  __ bind(&miss);
2196  // ecx: function name.
2197  GenerateMissBranch();
2198 
2199  // Return the generated code.
2200  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
2201 }
2202 
2203 
2204 Handle<Code> CallStubCompiler::CompileFastApiCall(
2205  const CallOptimization& optimization,
2206  Handle<Object> object,
2207  Handle<JSObject> holder,
2208  Handle<JSGlobalPropertyCell> cell,
2209  Handle<JSFunction> function,
2210  Handle<String> name) {
2211  ASSERT(optimization.is_simple_api_call());
2212  // Bail out if object is a global object as we don't want to
2213  // repatch it to global receiver.
2214  if (object->IsGlobalObject()) return Handle<Code>::null();
2215  if (!cell.is_null()) return Handle<Code>::null();
2216  if (!object->IsJSObject()) return Handle<Code>::null();
2217  int depth = optimization.GetPrototypeDepthOfExpectedType(
2218  Handle<JSObject>::cast(object), holder);
2219  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
2220 
2221  Label miss, miss_before_stack_reserved;
2222 
2223  GenerateNameCheck(name, &miss_before_stack_reserved);
2224 
2225  // Get the receiver from the stack.
2226  const int argc = arguments().immediate();
2227  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2228 
2229  // Check that the receiver isn't a smi.
2230  __ JumpIfSmi(edx, &miss_before_stack_reserved);
2231 
2232  Counters* counters = isolate()->counters();
2233  __ IncrementCounter(counters->call_const(), 1);
2234  __ IncrementCounter(counters->call_const_fast_api(), 1);
2235 
2236  // Allocate space for v8::Arguments implicit values. Must be initialized
2237  // before calling any runtime function.
2238  __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
2239 
2240  // Check that the maps haven't changed and find a Holder as a side effect.
2241  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
2242  name, depth, &miss);
2243 
2244  // Move the return address on top of the stack.
2245  __ mov(eax, Operand(esp, 4 * kPointerSize));
2246  __ mov(Operand(esp, 0 * kPointerSize), eax);
2247 
2248  // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
2249  // duplicate of return address and will be overwritten.
2250  GenerateFastApiCall(masm(), optimization, argc);
2251 
2252  __ bind(&miss);
2253  __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
2254 
2255  __ bind(&miss_before_stack_reserved);
2256  GenerateMissBranch();
2257 
2258  // Return the generated code.
2259  return GetCode(function);
2260 }
2261 
2262 
2263 Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
2264  Handle<JSObject> holder,
2265  Handle<JSFunction> function,
2266  Handle<String> name,
2267  CheckType check) {
2268  // ----------- S t a t e -------------
2269  // -- ecx : name
2270  // -- esp[0] : return address
2271  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2272  // -- ...
2273  // -- esp[(argc + 1) * 4] : receiver
2274  // -----------------------------------
2275 
2276  if (HasCustomCallGenerator(function)) {
2277  Handle<Code> code = CompileCustomCall(object, holder,
2278  Handle<JSGlobalPropertyCell>::null(),
2279  function, name);
2280  // A null handle means bail out to the regular compiler code below.
2281  if (!code.is_null()) return code;
2282  }
2283 
2284  Label miss;
2285  GenerateNameCheck(name, &miss);
2286 
2287  // Get the receiver from the stack.
2288  const int argc = arguments().immediate();
2289  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2290 
2291  // Check that the receiver isn't a smi.
2292  if (check != NUMBER_CHECK) {
2293  __ JumpIfSmi(edx, &miss);
2294  }
2295 
2296  // Make sure that it's okay not to patch the on stack receiver
2297  // unless we're doing a receiver map check.
2298  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2299  switch (check) {
2300  case RECEIVER_MAP_CHECK:
2301  __ IncrementCounter(isolate()->counters()->call_const(), 1);
2302 
2303  // Check that the maps haven't changed.
2304  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax,
2305  edi, name, &miss);
2306 
2307  // Patch the receiver on the stack with the global proxy if
2308  // necessary.
2309  if (object->IsGlobalObject()) {
2311  __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2312  }
2313  break;
2314 
2315  case STRING_CHECK:
2316  if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2317  // Check that the object is a string or a symbol.
2318  __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
2319  __ j(above_equal, &miss);
2320  // Check that the maps starting from the prototype haven't changed.
2321  GenerateDirectLoadGlobalFunctionPrototype(
2322  masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
2323  CheckPrototypes(
2324  Handle<JSObject>(JSObject::cast(object->GetPrototype())),
2325  eax, holder, ebx, edx, edi, name, &miss);
2326  } else {
2327  // Calling non-strict non-builtins with a value as the receiver
2328  // requires boxing.
2329  __ jmp(&miss);
2330  }
2331  break;
2332 
2333  case NUMBER_CHECK:
2334  if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2335  Label fast;
2336  // Check that the object is a smi or a heap number.
2337  __ JumpIfSmi(edx, &fast);
2338  __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
2339  __ j(not_equal, &miss);
2340  __ bind(&fast);
2341  // Check that the maps starting from the prototype haven't changed.
2342  GenerateDirectLoadGlobalFunctionPrototype(
2343  masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
2344  CheckPrototypes(
2345  Handle<JSObject>(JSObject::cast(object->GetPrototype())),
2346  eax, holder, ebx, edx, edi, name, &miss);
2347  } else {
2348  // Calling non-strict non-builtins with a value as the receiver
2349  // requires boxing.
2350  __ jmp(&miss);
2351  }
2352  break;
2353 
2354  case BOOLEAN_CHECK:
2355  if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2356  Label fast;
2357  // Check that the object is a boolean.
2358  __ cmp(edx, factory()->true_value());
2359  __ j(equal, &fast);
2360  __ cmp(edx, factory()->false_value());
2361  __ j(not_equal, &miss);
2362  __ bind(&fast);
2363  // Check that the maps starting from the prototype haven't changed.
2364  GenerateDirectLoadGlobalFunctionPrototype(
2365  masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
2366  CheckPrototypes(
2367  Handle<JSObject>(JSObject::cast(object->GetPrototype())),
2368  eax, holder, ebx, edx, edi, name, &miss);
2369  } else {
2370  // Calling non-strict non-builtins with a value as the receiver
2371  // requires boxing.
2372  __ jmp(&miss);
2373  }
2374  break;
2375  }
2376 
2377  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2379  : CALL_AS_METHOD;
2380  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2381  NullCallWrapper(), call_kind);
2382 
2383  // Handle call cache miss.
2384  __ bind(&miss);
2385  GenerateMissBranch();
2386 
2387  // Return the generated code.
2388  return GetCode(function);
2389 }
2390 
2391 
2392 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
2393  Handle<JSObject> holder,
2394  Handle<String> name) {
2395  // ----------- S t a t e -------------
2396  // -- ecx : name
2397  // -- esp[0] : return address
2398  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2399  // -- ...
2400  // -- esp[(argc + 1) * 4] : receiver
2401  // -----------------------------------
2402  Label miss;
2403 
2404  GenerateNameCheck(name, &miss);
2405 
2406  // Get the number of arguments.
2407  const int argc = arguments().immediate();
2408 
2409  LookupResult lookup(isolate());
2410  LookupPostInterceptor(holder, name, &lookup);
2411 
2412  // Get the receiver from the stack.
2413  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2414 
2415  CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_);
2416  compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax,
2417  &miss);
2418 
2419  // Restore receiver.
2420  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2421 
2422  // Check that the function really is a function.
2423  __ JumpIfSmi(eax, &miss);
2424  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2425  __ j(not_equal, &miss);
2426 
2427  // Patch the receiver on the stack with the global proxy if
2428  // necessary.
2429  if (object->IsGlobalObject()) {
2431  __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2432  }
2433 
2434  // Invoke the function.
2435  __ mov(edi, eax);
2436  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2438  : CALL_AS_METHOD;
2439  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
2440  NullCallWrapper(), call_kind);
2441 
2442  // Handle load cache miss.
2443  __ bind(&miss);
2444  GenerateMissBranch();
2445 
2446  // Return the generated code.
2447  return GetCode(INTERCEPTOR, name);
2448 }
2449 
2450 
2452  Handle<JSObject> object,
2453  Handle<GlobalObject> holder,
2454  Handle<JSGlobalPropertyCell> cell,
2455  Handle<JSFunction> function,
2456  Handle<String> name) {
2457  // ----------- S t a t e -------------
2458  // -- ecx : name
2459  // -- esp[0] : return address
2460  // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2461  // -- ...
2462  // -- esp[(argc + 1) * 4] : receiver
2463  // -----------------------------------
2464 
2465  if (HasCustomCallGenerator(function)) {
2466  Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
2467  // A null handle means bail out to the regular compiler code below.
2468  if (!code.is_null()) return code;
2469  }
2470 
2471  Label miss;
2472  GenerateNameCheck(name, &miss);
2473 
2474  // Get the number of arguments.
2475  const int argc = arguments().immediate();
2476  GenerateGlobalReceiverCheck(object, holder, name, &miss);
2477  GenerateLoadFunctionFromCell(cell, function, &miss);
2478 
2479  // Patch the receiver on the stack with the global proxy.
2480  if (object->IsGlobalObject()) {
2482  __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2483  }
2484 
2485  // Set up the context (function already in edi).
2487 
2488  // Jump to the cached code (tail call).
2489  Counters* counters = isolate()->counters();
2490  __ IncrementCounter(counters->call_global_inline(), 1);
2491  ParameterCount expected(function->shared()->formal_parameter_count());
2492  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2494  : CALL_AS_METHOD;
2495  // We call indirectly through the code field in the function to
2496  // allow recompilation to take effect without changing any of the
2497  // call sites.
2498  __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2499  expected, arguments(), JUMP_FUNCTION,
2500  NullCallWrapper(), call_kind);
2501 
2502  // Handle call cache miss.
2503  __ bind(&miss);
2504  __ IncrementCounter(counters->call_global_inline_miss(), 1);
2505  GenerateMissBranch();
2506 
2507  // Return the generated code.
2508  return GetCode(NORMAL, name);
2509 }
2510 
2511 
2512 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
2513  int index,
2514  Handle<Map> transition,
2515  Handle<String> name) {
2516  // ----------- S t a t e -------------
2517  // -- eax : value
2518  // -- ecx : name
2519  // -- edx : receiver
2520  // -- esp[0] : return address
2521  // -----------------------------------
2522  Label miss;
2523 
2524  // Generate store field code. Trashes the name register.
2525  GenerateStoreField(masm(),
2526  object,
2527  index,
2528  transition,
2529  name,
2530  edx, ecx, ebx, edi,
2531  &miss);
2532  // Handle store cache miss.
2533  __ bind(&miss);
2534  __ mov(ecx, Immediate(name)); // restore name
2535  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2536  __ jmp(ic, RelocInfo::CODE_TARGET);
2537 
2538  // Return the generated code.
2539  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2540 }
2541 
2542 
2544  Handle<JSObject> object,
2545  Handle<AccessorInfo> callback,
2546  Handle<String> name) {
2547  // ----------- S t a t e -------------
2548  // -- eax : value
2549  // -- ecx : name
2550  // -- edx : receiver
2551  // -- esp[0] : return address
2552  // -----------------------------------
2553  Label miss;
2554 
2555  // Check that the map of the object hasn't changed.
2556  __ CheckMap(edx, Handle<Map>(object->map()),
2558 
2559  // Perform global security token check if needed.
2560  if (object->IsJSGlobalProxy()) {
2561  __ CheckAccessGlobalProxy(edx, ebx, &miss);
2562  }
2563 
2564  // Stub never generated for non-global objects that require access
2565  // checks.
2566  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2567 
2568  __ pop(ebx); // remove the return address
2569  __ push(edx); // receiver
2570  __ push(Immediate(callback)); // callback info
2571  __ push(ecx); // name
2572  __ push(eax); // value
2573  __ push(ebx); // restore return address
2574 
2575  // Do tail-call to the runtime system.
2576  ExternalReference store_callback_property =
2577  ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2578  __ TailCallExternalReference(store_callback_property, 4, 1);
2579 
2580  // Handle store cache miss.
2581  __ bind(&miss);
2582  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2583  __ jmp(ic, RelocInfo::CODE_TARGET);
2584 
2585  // Return the generated code.
2586  return GetCode(CALLBACKS, name);
2587 }
2588 
2589 
2591  Handle<JSObject> receiver,
2592  Handle<JSFunction> setter,
2593  Handle<String> name) {
2594  // ----------- S t a t e -------------
2595  // -- eax : value
2596  // -- ecx : name
2597  // -- edx : receiver
2598  // -- esp[0] : return address
2599  // -----------------------------------
2600  Label miss;
2601 
2602  // Check that the map of the object hasn't changed.
2603  __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, DO_SMI_CHECK,
2605 
2606  {
2607  FrameScope scope(masm(), StackFrame::INTERNAL);
2608 
2609  // Save value register, so we can restore it later.
2610  __ push(eax);
2611 
2612  // Call the JavaScript getter with the receiver and the value on the stack.
2613  __ push(edx);
2614  __ push(eax);
2615  ParameterCount actual(1);
2616  __ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
2617  CALL_AS_METHOD);
2618 
2619  // We have to return the passed value, not the return value of the setter.
2620  __ pop(eax);
2621 
2622  // Restore context register.
2624  }
2625  __ ret(0);
2626 
2627  __ bind(&miss);
2628  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2629  __ jmp(ic, RelocInfo::CODE_TARGET);
2630 
2631  // Return the generated code.
2632  return GetCode(CALLBACKS, name);
2633 }
2634 
2635 
2637  Handle<JSObject> receiver,
2638  Handle<String> name) {
2639  // ----------- S t a t e -------------
2640  // -- eax : value
2641  // -- ecx : name
2642  // -- edx : receiver
2643  // -- esp[0] : return address
2644  // -----------------------------------
2645  Label miss;
2646 
2647  // Check that the map of the object hasn't changed.
2648  __ CheckMap(edx, Handle<Map>(receiver->map()),
2650 
2651  // Perform global security token check if needed.
2652  if (receiver->IsJSGlobalProxy()) {
2653  __ CheckAccessGlobalProxy(edx, ebx, &miss);
2654  }
2655 
2656  // Stub never generated for non-global objects that require access
2657  // checks.
2658  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2659 
2660  __ pop(ebx); // remove the return address
2661  __ push(edx); // receiver
2662  __ push(ecx); // name
2663  __ push(eax); // value
2664  __ push(Immediate(Smi::FromInt(strict_mode_)));
2665  __ push(ebx); // restore return address
2666 
2667  // Do tail-call to the runtime system.
2668  ExternalReference store_ic_property =
2669  ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2670  __ TailCallExternalReference(store_ic_property, 4, 1);
2671 
2672  // Handle store cache miss.
2673  __ bind(&miss);
2674  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2675  __ jmp(ic, RelocInfo::CODE_TARGET);
2676 
2677  // Return the generated code.
2678  return GetCode(INTERCEPTOR, name);
2679 }
2680 
2681 
2683  Handle<GlobalObject> object,
2684  Handle<JSGlobalPropertyCell> cell,
2685  Handle<String> name) {
2686  // ----------- S t a t e -------------
2687  // -- eax : value
2688  // -- ecx : name
2689  // -- edx : receiver
2690  // -- esp[0] : return address
2691  // -----------------------------------
2692  Label miss;
2693 
2694  // Check that the map of the global has not changed.
2696  Immediate(Handle<Map>(object->map())));
2697  __ j(not_equal, &miss);
2698 
2699  // Compute the cell operand to use.
2700  __ mov(ebx, Immediate(cell));
2701  Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
2702 
2703  // Check that the value in the cell is not the hole. If it is, this
2704  // cell could have been deleted and reintroducing the global needs
2705  // to update the property details in the property dictionary of the
2706  // global object. We bail out to the runtime system to do that.
2707  __ cmp(cell_operand, factory()->the_hole_value());
2708  __ j(equal, &miss);
2709 
2710  // Store the value in the cell.
2711  __ mov(cell_operand, eax);
2712  // No write barrier here, because cells are always rescanned.
2713 
2714  // Return the value (register eax).
2715  Counters* counters = isolate()->counters();
2716  __ IncrementCounter(counters->named_store_global_inline(), 1);
2717  __ ret(0);
2718 
2719  // Handle store cache miss.
2720  __ bind(&miss);
2721  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
2722  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2723  __ jmp(ic, RelocInfo::CODE_TARGET);
2724 
2725  // Return the generated code.
2726  return GetCode(NORMAL, name);
2727 }
2728 
2729 
2730 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
2731  int index,
2732  Handle<Map> transition,
2733  Handle<String> name) {
2734  // ----------- S t a t e -------------
2735  // -- eax : value
2736  // -- ecx : key
2737  // -- edx : receiver
2738  // -- esp[0] : return address
2739  // -----------------------------------
2740  Label miss;
2741 
2742  Counters* counters = isolate()->counters();
2743  __ IncrementCounter(counters->keyed_store_field(), 1);
2744 
2745  // Check that the name has not changed.
2746  __ cmp(ecx, Immediate(name));
2747  __ j(not_equal, &miss);
2748 
2749  // Generate store field code. Trashes the name register.
2750  GenerateStoreField(masm(),
2751  object,
2752  index,
2753  transition,
2754  name,
2755  edx, ecx, ebx, edi,
2756  &miss);
2757 
2758  // Handle store cache miss.
2759  __ bind(&miss);
2760  __ DecrementCounter(counters->keyed_store_field(), 1);
2761  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2762  __ jmp(ic, RelocInfo::CODE_TARGET);
2763 
2764  // Return the generated code.
2765  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2766 }
2767 
2768 
2770  Handle<Map> receiver_map) {
2771  // ----------- S t a t e -------------
2772  // -- eax : value
2773  // -- ecx : key
2774  // -- edx : receiver
2775  // -- esp[0] : return address
2776  // -----------------------------------
2777  ElementsKind elements_kind = receiver_map->elements_kind();
2778  bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
2779  Handle<Code> stub =
2780  KeyedStoreElementStub(is_jsarray, elements_kind, grow_mode_).GetCode();
2781 
2782  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
2783 
2784  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2785  __ jmp(ic, RelocInfo::CODE_TARGET);
2786 
2787  // Return the generated code.
2788  return GetCode(NORMAL, factory()->empty_string());
2789 }
2790 
2791 
2793  MapHandleList* receiver_maps,
2794  CodeHandleList* handler_stubs,
2795  MapHandleList* transitioned_maps) {
2796  // ----------- S t a t e -------------
2797  // -- eax : value
2798  // -- ecx : key
2799  // -- edx : receiver
2800  // -- esp[0] : return address
2801  // -----------------------------------
2802  Label miss;
2803  __ JumpIfSmi(edx, &miss, Label::kNear);
2804  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
2805  // ebx: receiver->map().
2806  for (int i = 0; i < receiver_maps->length(); ++i) {
2807  __ cmp(edi, receiver_maps->at(i));
2808  if (transitioned_maps->at(i).is_null()) {
2809  __ j(equal, handler_stubs->at(i));
2810  } else {
2811  Label next_map;
2812  __ j(not_equal, &next_map, Label::kNear);
2813  __ mov(ebx, Immediate(transitioned_maps->at(i)));
2814  __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
2815  __ bind(&next_map);
2816  }
2817  }
2818  __ bind(&miss);
2819  Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
2820  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
2821 
2822  // Return the generated code.
2823  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
2824 }
2825 
2826 
2827 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
2828  Handle<JSObject> object,
2829  Handle<JSObject> last) {
2830  // ----------- S t a t e -------------
2831  // -- ecx : name
2832  // -- edx : receiver
2833  // -- esp[0] : return address
2834  // -----------------------------------
2835  Label miss;
2836 
2837  // Check that the receiver isn't a smi.
2838  __ JumpIfSmi(edx, &miss);
2839 
2840  ASSERT(last->IsGlobalObject() || last->HasFastProperties());
2841 
2842  // Check the maps of the full prototype chain. Also check that
2843  // global property cells up to (but not including) the last object
2844  // in the prototype chain are empty.
2845  CheckPrototypes(object, edx, last, ebx, eax, edi, name, &miss);
2846 
2847  // If the last object in the prototype chain is a global object,
2848  // check that the global property cell is empty.
2849  if (last->IsGlobalObject()) {
2850  GenerateCheckPropertyCell(
2851  masm(), Handle<GlobalObject>::cast(last), name, eax, &miss);
2852  }
2853 
2854  // Return undefined if maps of the full prototype chain are still the
2855  // same and no global property with this name contains a value.
2856  __ mov(eax, isolate()->factory()->undefined_value());
2857  __ ret(0);
2858 
2859  __ bind(&miss);
2860  GenerateLoadMiss(masm(), Code::LOAD_IC);
2861 
2862  // Return the generated code.
2863  return GetCode(NONEXISTENT, factory()->empty_string());
2864 }
2865 
2866 
2867 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
2868  Handle<JSObject> holder,
2869  int index,
2870  Handle<String> name) {
2871  // ----------- S t a t e -------------
2872  // -- ecx : name
2873  // -- edx : receiver
2874  // -- esp[0] : return address
2875  // -----------------------------------
2876  Label miss;
2877 
2878  GenerateLoadField(object, holder, edx, ebx, eax, edi, index, name, &miss);
2879  __ bind(&miss);
2880  GenerateLoadMiss(masm(), Code::LOAD_IC);
2881 
2882  // Return the generated code.
2883  return GetCode(FIELD, name);
2884 }
2885 
2886 
2888  Handle<String> name,
2889  Handle<JSObject> object,
2890  Handle<JSObject> holder,
2891  Handle<AccessorInfo> callback) {
2892  // ----------- S t a t e -------------
2893  // -- ecx : name
2894  // -- edx : receiver
2895  // -- esp[0] : return address
2896  // -----------------------------------
2897  Label miss;
2898 
2899  GenerateLoadCallback(object, holder, edx, ecx, ebx, eax, edi, callback,
2900  name, &miss);
2901  __ bind(&miss);
2902  GenerateLoadMiss(masm(), Code::LOAD_IC);
2903 
2904  // Return the generated code.
2905  return GetCode(CALLBACKS, name);
2906 }
2907 
2908 
2910  Handle<String> name,
2911  Handle<JSObject> receiver,
2912  Handle<JSObject> holder,
2913  Handle<JSFunction> getter) {
2914  // ----------- S t a t e -------------
2915  // -- ecx : name
2916  // -- edx : receiver
2917  // -- esp[0] : return address
2918  // -----------------------------------
2919  Label miss;
2920 
2921  // Check that the maps haven't changed.
2922  __ JumpIfSmi(edx, &miss);
2923  CheckPrototypes(receiver, edx, holder, ebx, eax, edi, name, &miss);
2924 
2925  {
2926  FrameScope scope(masm(), StackFrame::INTERNAL);
2927 
2928  // Call the JavaScript getter with the receiver on the stack.
2929  __ push(edx);
2930  ParameterCount actual(0);
2931  __ InvokeFunction(getter, actual, CALL_FUNCTION, NullCallWrapper(),
2932  CALL_AS_METHOD);
2933 
2934  // Restore context register.
2936  }
2937  __ ret(0);
2938 
2939  __ bind(&miss);
2940  GenerateLoadMiss(masm(), Code::LOAD_IC);
2941 
2942  // Return the generated code.
2943  return GetCode(CALLBACKS, name);
2944 }
2945 
2946 
2947 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
2948  Handle<JSObject> holder,
2949  Handle<JSFunction> value,
2950  Handle<String> name) {
2951  // ----------- S t a t e -------------
2952  // -- ecx : name
2953  // -- edx : receiver
2954  // -- esp[0] : return address
2955  // -----------------------------------
2956  Label miss;
2957 
2958  GenerateLoadConstant(object, holder, edx, ebx, eax, edi, value, name, &miss);
2959  __ bind(&miss);
2960  GenerateLoadMiss(masm(), Code::LOAD_IC);
2961 
2962  // Return the generated code.
2963  return GetCode(CONSTANT_FUNCTION, name);
2964 }
2965 
2966 
2967 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver,
2968  Handle<JSObject> holder,
2969  Handle<String> name) {
2970  // ----------- S t a t e -------------
2971  // -- ecx : name
2972  // -- edx : receiver
2973  // -- esp[0] : return address
2974  // -----------------------------------
2975  Label miss;
2976 
2977  LookupResult lookup(isolate());
2978  LookupPostInterceptor(holder, name, &lookup);
2979 
2980  // TODO(368): Compile in the whole chain: all the interceptors in
2981  // prototypes and ultimate answer.
2982  GenerateLoadInterceptor(receiver, holder, &lookup, edx, ecx, eax, ebx, edi,
2983  name, &miss);
2984 
2985  __ bind(&miss);
2986  GenerateLoadMiss(masm(), Code::LOAD_IC);
2987 
2988  // Return the generated code.
2989  return GetCode(INTERCEPTOR, name);
2990 }
2991 
2992 
2994  Handle<JSObject> object,
2995  Handle<GlobalObject> holder,
2996  Handle<JSGlobalPropertyCell> cell,
2997  Handle<String> name,
2998  bool is_dont_delete) {
2999  // ----------- S t a t e -------------
3000  // -- ecx : name
3001  // -- edx : receiver
3002  // -- esp[0] : return address
3003  // -----------------------------------
3004  Label miss;
3005 
3006  // Check that the maps haven't changed.
3007  __ JumpIfSmi(edx, &miss);
3008  CheckPrototypes(object, edx, holder, ebx, eax, edi, name, &miss);
3009 
3010  // Get the value from the cell.
3011  if (Serializer::enabled()) {
3012  __ mov(ebx, Immediate(cell));
3014  } else {
3015  __ mov(ebx, Operand::Cell(cell));
3016  }
3017 
3018  // Check for deleted property if property can actually be deleted.
3019  if (!is_dont_delete) {
3020  __ cmp(ebx, factory()->the_hole_value());
3021  __ j(equal, &miss);
3022  } else if (FLAG_debug_code) {
3023  __ cmp(ebx, factory()->the_hole_value());
3024  __ Check(not_equal, "DontDelete cells can't contain the hole");
3025  }
3026 
3027  Counters* counters = isolate()->counters();
3028  __ IncrementCounter(counters->named_load_global_stub(), 1);
3029  __ mov(eax, ebx);
3030  __ ret(0);
3031 
3032  __ bind(&miss);
3033  __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
3034  GenerateLoadMiss(masm(), Code::LOAD_IC);
3035 
3036  // Return the generated code.
3037  return GetCode(NORMAL, name);
3038 }
3039 
3040 
3041 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
3042  Handle<JSObject> receiver,
3043  Handle<JSObject> holder,
3044  int index) {
3045  // ----------- S t a t e -------------
3046  // -- ecx : key
3047  // -- edx : receiver
3048  // -- esp[0] : return address
3049  // -----------------------------------
3050  Label miss;
3051 
3052  Counters* counters = isolate()->counters();
3053  __ IncrementCounter(counters->keyed_load_field(), 1);
3054 
3055  // Check that the name has not changed.
3056  __ cmp(ecx, Immediate(name));
3057  __ j(not_equal, &miss);
3058 
3059  GenerateLoadField(receiver, holder, edx, ebx, eax, edi, index, name, &miss);
3060 
3061  __ bind(&miss);
3062  __ DecrementCounter(counters->keyed_load_field(), 1);
3063  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3064 
3065  // Return the generated code.
3066  return GetCode(FIELD, name);
3067 }
3068 
3069 
3071  Handle<String> name,
3072  Handle<JSObject> receiver,
3073  Handle<JSObject> holder,
3074  Handle<AccessorInfo> callback) {
3075  // ----------- S t a t e -------------
3076  // -- ecx : key
3077  // -- edx : receiver
3078  // -- esp[0] : return address
3079  // -----------------------------------
3080  Label miss;
3081 
3082  Counters* counters = isolate()->counters();
3083  __ IncrementCounter(counters->keyed_load_callback(), 1);
3084 
3085  // Check that the name has not changed.
3086  __ cmp(ecx, Immediate(name));
3087  __ j(not_equal, &miss);
3088 
3089  GenerateLoadCallback(receiver, holder, edx, ecx, ebx, eax, edi, callback,
3090  name, &miss);
3091 
3092  __ bind(&miss);
3093  __ DecrementCounter(counters->keyed_load_callback(), 1);
3094  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3095 
3096  // Return the generated code.
3097  return GetCode(CALLBACKS, name);
3098 }
3099 
3100 
3102  Handle<String> name,
3103  Handle<JSObject> receiver,
3104  Handle<JSObject> holder,
3105  Handle<JSFunction> value) {
3106  // ----------- S t a t e -------------
3107  // -- ecx : key
3108  // -- edx : receiver
3109  // -- esp[0] : return address
3110  // -----------------------------------
3111  Label miss;
3112 
3113  Counters* counters = isolate()->counters();
3114  __ IncrementCounter(counters->keyed_load_constant_function(), 1);
3115 
3116  // Check that the name has not changed.
3117  __ cmp(ecx, Immediate(name));
3118  __ j(not_equal, &miss);
3119 
3120  GenerateLoadConstant(
3121  receiver, holder, edx, ebx, eax, edi, value, name, &miss);
3122  __ bind(&miss);
3123  __ DecrementCounter(counters->keyed_load_constant_function(), 1);
3124  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3125 
3126  // Return the generated code.
3127  return GetCode(CONSTANT_FUNCTION, name);
3128 }
3129 
3130 
3132  Handle<JSObject> receiver,
3133  Handle<JSObject> holder,
3134  Handle<String> name) {
3135  // ----------- S t a t e -------------
3136  // -- ecx : key
3137  // -- edx : receiver
3138  // -- esp[0] : return address
3139  // -----------------------------------
3140  Label miss;
3141 
3142  Counters* counters = isolate()->counters();
3143  __ IncrementCounter(counters->keyed_load_interceptor(), 1);
3144 
3145  // Check that the name has not changed.
3146  __ cmp(ecx, Immediate(name));
3147  __ j(not_equal, &miss);
3148 
3149  LookupResult lookup(isolate());
3150  LookupPostInterceptor(holder, name, &lookup);
3151  GenerateLoadInterceptor(receiver, holder, &lookup, edx, ecx, eax, ebx, edi,
3152  name, &miss);
3153  __ bind(&miss);
3154  __ DecrementCounter(counters->keyed_load_interceptor(), 1);
3155  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3156 
3157  // Return the generated code.
3158  return GetCode(INTERCEPTOR, name);
3159 }
3160 
3161 
3163  Handle<String> name) {
3164  // ----------- S t a t e -------------
3165  // -- ecx : key
3166  // -- edx : receiver
3167  // -- esp[0] : return address
3168  // -----------------------------------
3169  Label miss;
3170 
3171  Counters* counters = isolate()->counters();
3172  __ IncrementCounter(counters->keyed_load_array_length(), 1);
3173 
3174  // Check that the name has not changed.
3175  __ cmp(ecx, Immediate(name));
3176  __ j(not_equal, &miss);
3177 
3178  GenerateLoadArrayLength(masm(), edx, eax, &miss);
3179  __ bind(&miss);
3180  __ DecrementCounter(counters->keyed_load_array_length(), 1);
3181  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3182 
3183  // Return the generated code.
3184  return GetCode(CALLBACKS, name);
3185 }
3186 
3187 
3189  Handle<String> name) {
3190  // ----------- S t a t e -------------
3191  // -- ecx : key
3192  // -- edx : receiver
3193  // -- esp[0] : return address
3194  // -----------------------------------
3195  Label miss;
3196 
3197  Counters* counters = isolate()->counters();
3198  __ IncrementCounter(counters->keyed_load_string_length(), 1);
3199 
3200  // Check that the name has not changed.
3201  __ cmp(ecx, Immediate(name));
3202  __ j(not_equal, &miss);
3203 
3204  GenerateLoadStringLength(masm(), edx, eax, ebx, &miss, true);
3205  __ bind(&miss);
3206  __ DecrementCounter(counters->keyed_load_string_length(), 1);
3207  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3208 
3209  // Return the generated code.
3210  return GetCode(CALLBACKS, name);
3211 }
3212 
3213 
3215  Handle<String> name) {
3216  // ----------- S t a t e -------------
3217  // -- ecx : key
3218  // -- edx : receiver
3219  // -- esp[0] : return address
3220  // -----------------------------------
3221  Label miss;
3222 
3223  Counters* counters = isolate()->counters();
3224  __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
3225 
3226  // Check that the name has not changed.
3227  __ cmp(ecx, Immediate(name));
3228  __ j(not_equal, &miss);
3229 
3230  GenerateLoadFunctionPrototype(masm(), edx, eax, ebx, &miss);
3231  __ bind(&miss);
3232  __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
3233  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3234 
3235  // Return the generated code.
3236  return GetCode(CALLBACKS, name);
3237 }
3238 
3239 
3241  Handle<Map> receiver_map) {
3242  // ----------- S t a t e -------------
3243  // -- ecx : key
3244  // -- edx : receiver
3245  // -- esp[0] : return address
3246  // -----------------------------------
3247 
3248  ElementsKind elements_kind = receiver_map->elements_kind();
3249  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
3250 
3251  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
3252 
3253  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3254 
3255  // Return the generated code.
3256  return GetCode(NORMAL, factory()->empty_string());
3257 }
3258 
3259 
3261  MapHandleList* receiver_maps,
3262  CodeHandleList* handler_ics) {
3263  // ----------- S t a t e -------------
3264  // -- ecx : key
3265  // -- edx : receiver
3266  // -- esp[0] : return address
3267  // -----------------------------------
3268  Label miss;
3269  __ JumpIfSmi(edx, &miss);
3270 
3271  Register map_reg = ebx;
3272  __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
3273  int receiver_count = receiver_maps->length();
3274  for (int current = 0; current < receiver_count; ++current) {
3275  __ cmp(map_reg, receiver_maps->at(current));
3276  __ j(equal, handler_ics->at(current));
3277  }
3278 
3279  __ bind(&miss);
3280  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3281 
3282  // Return the generated code.
3283  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
3284 }
3285 
3286 
3287 // Specialized stub for constructing objects from functions which only have only
3288 // simple assignments of the form this.x = ...; in their body.
3290  Handle<JSFunction> function) {
3291  // ----------- S t a t e -------------
3292  // -- eax : argc
3293  // -- edi : constructor
3294  // -- esp[0] : return address
3295  // -- esp[4] : last argument
3296  // -----------------------------------
3297  Label generic_stub_call;
3298 #ifdef ENABLE_DEBUGGER_SUPPORT
3299  // Check to see whether there are any break points in the function code. If
3300  // there are jump to the generic constructor stub which calls the actual
3301  // code for the function thereby hitting the break points.
3304  __ cmp(ebx, factory()->undefined_value());
3305  __ j(not_equal, &generic_stub_call);
3306 #endif
3307 
3308  // Load the initial map and verify that it is in fact a map.
3310  // Will both indicate a NULL and a Smi.
3311  __ JumpIfSmi(ebx, &generic_stub_call);
3312  __ CmpObjectType(ebx, MAP_TYPE, ecx);
3313  __ j(not_equal, &generic_stub_call);
3314 
3315 #ifdef DEBUG
3316  // Cannot construct functions this way.
3317  // edi: constructor
3318  // ebx: initial map
3319  __ CmpInstanceType(ebx, JS_FUNCTION_TYPE);
3320  __ Assert(not_equal, "Function constructed by construct stub.");
3321 #endif
3322 
3323  // Now allocate the JSObject on the heap by moving the new space allocation
3324  // top forward.
3325  // edi: constructor
3326  // ebx: initial map
3327  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
3328  __ shl(ecx, kPointerSizeLog2);
3329  __ AllocateInNewSpace(ecx, edx, ecx, no_reg,
3330  &generic_stub_call, NO_ALLOCATION_FLAGS);
3331 
3332  // Allocated the JSObject, now initialize the fields and add the heap tag.
3333  // ebx: initial map
3334  // edx: JSObject (untagged)
3335  __ mov(Operand(edx, JSObject::kMapOffset), ebx);
3336  __ mov(ebx, factory()->empty_fixed_array());
3337  __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx);
3338  __ mov(Operand(edx, JSObject::kElementsOffset), ebx);
3339 
3340  // Push the allocated object to the stack. This is the object that will be
3341  // returned (after it is tagged).
3342  __ push(edx);
3343 
3344  // eax: argc
3345  // edx: JSObject (untagged)
3346  // Load the address of the first in-object property into edx.
3347  __ lea(edx, Operand(edx, JSObject::kHeaderSize));
3348  // Calculate the location of the first argument. The stack contains the
3349  // allocated object and the return address on top of the argc arguments.
3350  __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize));
3351 
3352  // Use edi for holding undefined which is used in several places below.
3353  __ mov(edi, factory()->undefined_value());
3354 
3355  // eax: argc
3356  // ecx: first argument
3357  // edx: first in-object property of the JSObject
3358  // edi: undefined
3359  // Fill the initialized properties with a constant value or a passed argument
3360  // depending on the this.x = ...; assignment in the function.
3361  Handle<SharedFunctionInfo> shared(function->shared());
3362  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3363  if (shared->IsThisPropertyAssignmentArgument(i)) {
3364  // Check if the argument assigned to the property is actually passed.
3365  // If argument is not passed the property is set to undefined,
3366  // otherwise find it on the stack.
3367  int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3368  __ mov(ebx, edi);
3369  __ cmp(eax, arg_number);
3371  CpuFeatures::Scope use_cmov(CMOV);
3372  __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize));
3373  } else {
3374  Label not_passed;
3375  __ j(below_equal, &not_passed);
3376  __ mov(ebx, Operand(ecx, arg_number * -kPointerSize));
3377  __ bind(&not_passed);
3378  }
3379  // Store value in the property.
3380  __ mov(Operand(edx, i * kPointerSize), ebx);
3381  } else {
3382  // Set the property to the constant value.
3383  Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3384  __ mov(Operand(edx, i * kPointerSize), Immediate(constant));
3385  }
3386  }
3387 
3388  // Fill the unused in-object property fields with undefined.
3389  ASSERT(function->has_initial_map());
3390  for (int i = shared->this_property_assignments_count();
3391  i < function->initial_map()->inobject_properties();
3392  i++) {
3393  __ mov(Operand(edx, i * kPointerSize), edi);
3394  }
3395 
3396  // Move argc to ebx and retrieve and tag the JSObject to return.
3397  __ mov(ebx, eax);
3398  __ pop(eax);
3399  __ or_(eax, Immediate(kHeapObjectTag));
3400 
3401  // Remove caller arguments and receiver from the stack and return.
3402  __ pop(ecx);
3403  __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize));
3404  __ push(ecx);
3405  Counters* counters = isolate()->counters();
3406  __ IncrementCounter(counters->constructed_objects(), 1);
3407  __ IncrementCounter(counters->constructed_objects_stub(), 1);
3408  __ ret(0);
3409 
3410  // Jump to the generic stub in case the specialized code cannot handle the
3411  // construction.
3412  __ bind(&generic_stub_call);
3413  Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric();
3414  __ jmp(code, RelocInfo::CODE_TARGET);
3415 
3416  // Return the generated code.
3417  return GetCode();
3418 }
3419 
3420 
3421 #undef __
3422 #define __ ACCESS_MASM(masm)
3423 
3424 
3426  MacroAssembler* masm) {
3427  // ----------- S t a t e -------------
3428  // -- ecx : key
3429  // -- edx : receiver
3430  // -- esp[0] : return address
3431  // -----------------------------------
3432  Label slow, miss_force_generic;
3433 
3434  // This stub is meant to be tail-jumped to, the receiver must already
3435  // have been verified by the caller to not be a smi.
3436  __ JumpIfNotSmi(ecx, &miss_force_generic);
3437  __ mov(ebx, ecx);
3438  __ SmiUntag(ebx);
3440 
3441  // Push receiver on the stack to free up a register for the dictionary
3442  // probing.
3443  __ push(edx);
3444  __ LoadFromNumberDictionary(&slow, eax, ecx, ebx, edx, edi, eax);
3445  // Pop receiver before returning.
3446  __ pop(edx);
3447  __ ret(0);
3448 
3449  __ bind(&slow);
3450  __ pop(edx);
3451 
3452  // ----------- S t a t e -------------
3453  // -- ecx : key
3454  // -- edx : receiver
3455  // -- esp[0] : return address
3456  // -----------------------------------
3457 
3458  Handle<Code> slow_ic =
3459  masm->isolate()->builtins()->KeyedLoadIC_Slow();
3460  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3461 
3462  __ bind(&miss_force_generic);
3463  // ----------- S t a t e -------------
3464  // -- ecx : key
3465  // -- edx : receiver
3466  // -- esp[0] : return address
3467  // -----------------------------------
3468 
3469  Handle<Code> miss_force_generic_ic =
3470  masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3471  __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET);
3472 }
3473 
3474 
3475 static void GenerateSmiKeyCheck(MacroAssembler* masm,
3476  Register key,
3477  Register scratch,
3478  XMMRegister xmm_scratch0,
3479  XMMRegister xmm_scratch1,
3480  Label* fail) {
3481  // Check that key is a smi and if SSE2 is available a heap number
3482  // containing a smi and branch if the check fails.
3484  CpuFeatures::Scope use_sse2(SSE2);
3485  Label key_ok;
3486  __ JumpIfSmi(key, &key_ok);
3488  Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map())));
3489  __ j(not_equal, fail);
3490  __ movdbl(xmm_scratch0, FieldOperand(key, HeapNumber::kValueOffset));
3491  __ cvttsd2si(scratch, Operand(xmm_scratch0));
3492  __ cvtsi2sd(xmm_scratch1, scratch);
3493  __ ucomisd(xmm_scratch1, xmm_scratch0);
3494  __ j(not_equal, fail);
3495  __ j(parity_even, fail); // NaN.
3496  // Check if the key fits in the smi range.
3497  __ cmp(scratch, 0xc0000000);
3498  __ j(sign, fail);
3499  __ SmiTag(scratch);
3500  __ mov(key, scratch);
3501  __ bind(&key_ok);
3502  } else {
3503  __ JumpIfNotSmi(key, fail);
3504  }
3505 }
3506 
3507 
3509  MacroAssembler* masm,
3510  ElementsKind elements_kind) {
3511  // ----------- S t a t e -------------
3512  // -- ecx : key
3513  // -- edx : receiver
3514  // -- esp[0] : return address
3515  // -----------------------------------
3516  Label miss_force_generic, failed_allocation, slow;
3517 
3518  // This stub is meant to be tail-jumped to, the receiver must already
3519  // have been verified by the caller to not be a smi.
3520 
3521  // Check that the key is a smi or a heap number convertible to a smi.
3522  GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic);
3523 
3524  // Check that the index is in range.
3525  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3527  // Unsigned comparison catches both negative and too-large values.
3528  __ j(above_equal, &miss_force_generic);
3530  // ebx: base pointer of external storage
3531  switch (elements_kind) {
3533  __ SmiUntag(ecx); // Untag the index.
3534  __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
3535  break;
3538  __ SmiUntag(ecx); // Untag the index.
3539  __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
3540  break;
3542  __ movsx_w(eax, Operand(ebx, ecx, times_1, 0));
3543  break;
3545  __ movzx_w(eax, Operand(ebx, ecx, times_1, 0));
3546  break;
3548  case EXTERNAL_INT_ELEMENTS:
3549  __ mov(eax, Operand(ebx, ecx, times_2, 0));
3550  break;
3552  __ fld_s(Operand(ebx, ecx, times_2, 0));
3553  break;
3555  __ fld_d(Operand(ebx, ecx, times_4, 0));
3556  break;
3557  default:
3558  UNREACHABLE();
3559  break;
3560  }
3561 
3562  // For integer array types:
3563  // eax: value
3564  // For floating-point array type:
3565  // FP(0): value
3566 
3567  if (elements_kind == EXTERNAL_INT_ELEMENTS ||
3568  elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
3569  // For the Int and UnsignedInt array types, we need to see whether
3570  // the value can be represented in a Smi. If not, we need to convert
3571  // it to a HeapNumber.
3572  Label box_int;
3573  if (elements_kind == EXTERNAL_INT_ELEMENTS) {
3574  __ cmp(eax, 0xc0000000);
3575  __ j(sign, &box_int);
3576  } else {
3577  ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
3578  // The test is different for unsigned int values. Since we need
3579  // the value to be in the range of a positive smi, we can't
3580  // handle either of the top two bits being set in the value.
3581  __ test(eax, Immediate(0xc0000000));
3582  __ j(not_zero, &box_int);
3583  }
3584 
3585  __ SmiTag(eax);
3586  __ ret(0);
3587 
3588  __ bind(&box_int);
3589 
3590  // Allocate a HeapNumber for the int and perform int-to-double
3591  // conversion.
3592  if (elements_kind == EXTERNAL_INT_ELEMENTS) {
3593  __ push(eax);
3594  __ fild_s(Operand(esp, 0));
3595  __ pop(eax);
3596  } else {
3597  ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
3598  // Need to zero-extend the value.
3599  // There's no fild variant for unsigned values, so zero-extend
3600  // to a 64-bit int manually.
3601  __ push(Immediate(0));
3602  __ push(eax);
3603  __ fild_d(Operand(esp, 0));
3604  __ pop(eax);
3605  __ pop(eax);
3606  }
3607  // FP(0): value
3608  __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation);
3609  // Set the value.
3611  __ ret(0);
3612  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3613  elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3614  // For the floating-point array type, we need to always allocate a
3615  // HeapNumber.
3616  __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation);
3617  // Set the value.
3619  __ ret(0);
3620  } else {
3621  __ SmiTag(eax);
3622  __ ret(0);
3623  }
3624 
3625  // If we fail allocation of the HeapNumber, we still have a value on
3626  // top of the FPU stack. Remove it.
3627  __ bind(&failed_allocation);
3628  __ fstp(0);
3629  // Fall through to slow case.
3630 
3631  // Slow case: Jump to runtime.
3632  __ bind(&slow);
3633  Counters* counters = masm->isolate()->counters();
3634  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3635 
3636  // ----------- S t a t e -------------
3637  // -- ecx : key
3638  // -- edx : receiver
3639  // -- esp[0] : return address
3640  // -----------------------------------
3641 
3642  Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3643  __ jmp(ic, RelocInfo::CODE_TARGET);
3644 
3645  // ----------- S t a t e -------------
3646  // -- ecx : key
3647  // -- edx : receiver
3648  // -- esp[0] : return address
3649  // -----------------------------------
3650 
3651  // Miss case: Jump to runtime.
3652  __ bind(&miss_force_generic);
3653  Handle<Code> miss_ic =
3654  masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3655  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3656 }
3657 
3658 
3660  MacroAssembler* masm,
3661  ElementsKind elements_kind) {
3662  // ----------- S t a t e -------------
3663  // -- eax : value
3664  // -- ecx : key
3665  // -- edx : receiver
3666  // -- esp[0] : return address
3667  // -----------------------------------
3668  Label miss_force_generic, slow, check_heap_number;
3669 
3670  // This stub is meant to be tail-jumped to, the receiver must already
3671  // have been verified by the caller to not be a smi.
3672 
3673  // Check that the key is a smi or a heap number convertible to a smi.
3674  GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic);
3675 
3676  // Check that the index is in range.
3677  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3679  // Unsigned comparison catches both negative and too-large values.
3680  __ j(above_equal, &slow);
3681 
3682  // Handle both smis and HeapNumbers in the fast path. Go to the
3683  // runtime for all other kinds of values.
3684  // eax: value
3685  // edx: receiver
3686  // ecx: key
3687  // edi: elements array
3688  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
3689  __ JumpIfNotSmi(eax, &slow);
3690  } else {
3691  __ JumpIfNotSmi(eax, &check_heap_number);
3692  }
3693 
3694  // smi case
3695  __ mov(ebx, eax); // Preserve the value in eax as the return value.
3696  __ SmiUntag(ebx);
3698  // edi: base pointer of external storage
3699  switch (elements_kind) {
3701  __ ClampUint8(ebx);
3702  __ SmiUntag(ecx);
3703  __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
3704  break;
3707  __ SmiUntag(ecx);
3708  __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
3709  break;
3712  __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
3713  break;
3714  case EXTERNAL_INT_ELEMENTS:
3716  __ mov(Operand(edi, ecx, times_2, 0), ebx);
3717  break;
3720  // Need to perform int-to-float conversion.
3721  __ push(ebx);
3722  __ fild_s(Operand(esp, 0));
3723  __ pop(ebx);
3724  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
3725  __ fstp_s(Operand(edi, ecx, times_2, 0));
3726  } else { // elements_kind == EXTERNAL_DOUBLE_ELEMENTS.
3727  __ fstp_d(Operand(edi, ecx, times_4, 0));
3728  }
3729  break;
3730  default:
3731  UNREACHABLE();
3732  break;
3733  }
3734  __ ret(0); // Return the original value.
3735 
3736  // TODO(danno): handle heap number -> pixel array conversion
3737  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
3738  __ bind(&check_heap_number);
3739  // eax: value
3740  // edx: receiver
3741  // ecx: key
3742  // edi: elements array
3744  Immediate(masm->isolate()->factory()->heap_number_map()));
3745  __ j(not_equal, &slow);
3746 
3747  // The WebGL specification leaves the behavior of storing NaN and
3748  // +/-Infinity into integer arrays basically undefined. For more
3749  // reproducible behavior, convert these to zero.
3751  // edi: base pointer of external storage
3752  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
3754  __ fstp_s(Operand(edi, ecx, times_2, 0));
3755  __ ret(0);
3756  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3758  __ fstp_d(Operand(edi, ecx, times_4, 0));
3759  __ ret(0);
3760  } else {
3761  // Perform float-to-int conversion with truncation (round-to-zero)
3762  // behavior.
3763 
3764  // For the moment we make the slow call to the runtime on
3765  // processors that don't support SSE2. The code in IntegerConvert
3766  // (code-stubs-ia32.cc) is roughly what is needed here though the
3767  // conversion failure case does not need to be handled.
3769  if ((elements_kind == EXTERNAL_INT_ELEMENTS ||
3770  elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) &&
3772  CpuFeatures::Scope scope(SSE3);
3773  // fisttp stores values as signed integers. To represent the
3774  // entire range of int and unsigned int arrays, store as a
3775  // 64-bit int and discard the high 32 bits.
3777  __ sub(esp, Immediate(2 * kPointerSize));
3778  __ fisttp_d(Operand(esp, 0));
3779 
3780  // If conversion failed (NaN, infinity, or a number outside
3781  // signed int64 range), the result is 0x8000000000000000, and
3782  // we must handle this case in the runtime.
3783  Label ok;
3784  __ cmp(Operand(esp, kPointerSize), Immediate(0x80000000u));
3785  __ j(not_equal, &ok);
3786  __ cmp(Operand(esp, 0), Immediate(0));
3787  __ j(not_equal, &ok);
3788  __ add(esp, Immediate(2 * kPointerSize)); // Restore the stack.
3789  __ jmp(&slow);
3790 
3791  __ bind(&ok);
3792  __ pop(ebx);
3793  __ add(esp, Immediate(kPointerSize));
3794  __ mov(Operand(edi, ecx, times_2, 0), ebx);
3795  } else {
3797  CpuFeatures::Scope scope(SSE2);
3798  __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset));
3799  __ cmp(ebx, 0x80000000u);
3800  __ j(equal, &slow);
3801  // ebx: untagged integer value
3802  switch (elements_kind) {
3804  __ ClampUint8(ebx);
3805  // Fall through.
3808  __ SmiUntag(ecx);
3809  __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
3810  break;
3813  __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
3814  break;
3815  case EXTERNAL_INT_ELEMENTS:
3817  __ mov(Operand(edi, ecx, times_2, 0), ebx);
3818  break;
3819  default:
3820  UNREACHABLE();
3821  break;
3822  }
3823  }
3824  __ ret(0); // Return original value.
3825  }
3826  }
3827  }
3828 
3829  // Slow case: call runtime.
3830  __ bind(&slow);
3831  Counters* counters = masm->isolate()->counters();
3832  __ IncrementCounter(counters->keyed_store_external_array_slow(), 1);
3833 
3834  // ----------- S t a t e -------------
3835  // -- eax : value
3836  // -- ecx : key
3837  // -- edx : receiver
3838  // -- esp[0] : return address
3839  // -----------------------------------
3840 
3841  Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3842  __ jmp(ic, RelocInfo::CODE_TARGET);
3843 
3844  // ----------- S t a t e -------------
3845  // -- eax : value
3846  // -- ecx : key
3847  // -- edx : receiver
3848  // -- esp[0] : return address
3849  // -----------------------------------
3850 
3851  __ bind(&miss_force_generic);
3852  Handle<Code> miss_ic =
3853  masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3854  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3855 }
3856 
3857 
3858 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3859  // ----------- S t a t e -------------
3860  // -- ecx : key
3861  // -- edx : receiver
3862  // -- esp[0] : return address
3863  // -----------------------------------
3864  Label miss_force_generic;
3865 
3866  // This stub is meant to be tail-jumped to, the receiver must already
3867  // have been verified by the caller to not be a smi.
3868 
3869  // Check that the key is a smi or a heap number convertible to a smi.
3870  GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic);
3871 
3872  // Get the elements array.
3874  __ AssertFastElements(eax);
3875 
3876  // Check that the key is within bounds.
3878  __ j(above_equal, &miss_force_generic);
3879 
3880  // Load the result and make sure it's not the hole.
3881  __ mov(ebx, Operand(eax, ecx, times_2,
3882  FixedArray::kHeaderSize - kHeapObjectTag));
3883  __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
3884  __ j(equal, &miss_force_generic);
3885  __ mov(eax, ebx);
3886  __ ret(0);
3887 
3888  __ bind(&miss_force_generic);
3889  Handle<Code> miss_ic =
3890  masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3891  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3892 }
3893 
3894 
3896  MacroAssembler* masm) {
3897  // ----------- S t a t e -------------
3898  // -- ecx : key
3899  // -- edx : receiver
3900  // -- esp[0] : return address
3901  // -----------------------------------
3902  Label miss_force_generic, slow_allocate_heapnumber;
3903 
3904  // This stub is meant to be tail-jumped to, the receiver must already
3905  // have been verified by the caller to not be a smi.
3906 
3907  // Check that the key is a smi or a heap number convertible to a smi.
3908  GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic);
3909 
3910  // Get the elements array.
3912  __ AssertFastElements(eax);
3913 
3914  // Check that the key is within bounds.
3916  __ j(above_equal, &miss_force_generic);
3917 
3918  // Check for the hole
3919  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
3920  __ cmp(FieldOperand(eax, ecx, times_4, offset), Immediate(kHoleNanUpper32));
3921  __ j(equal, &miss_force_generic);
3922 
3923  // Always allocate a heap number for the result.
3925  CpuFeatures::Scope use_sse2(SSE2);
3926  __ movdbl(xmm0, FieldOperand(eax, ecx, times_4,
3928  } else {
3930  }
3931  __ AllocateHeapNumber(eax, ebx, edi, &slow_allocate_heapnumber);
3932  // Set the value.
3934  CpuFeatures::Scope use_sse2(SSE2);
3936  } else {
3938  }
3939  __ ret(0);
3940 
3941  __ bind(&slow_allocate_heapnumber);
3942  // A value was pushed on the floating point stack before the allocation, if
3943  // the allocation fails it needs to be removed.
3945  __ fstp(0);
3946  }
3947  Handle<Code> slow_ic =
3948  masm->isolate()->builtins()->KeyedLoadIC_Slow();
3949  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3950 
3951  __ bind(&miss_force_generic);
3952  Handle<Code> miss_ic =
3953  masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3954  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3955 }
3956 
3957 
3959  MacroAssembler* masm,
3960  bool is_js_array,
3961  ElementsKind elements_kind,
3962  KeyedAccessGrowMode grow_mode) {
3963  // ----------- S t a t e -------------
3964  // -- eax : value
3965  // -- ecx : key
3966  // -- edx : receiver
3967  // -- esp[0] : return address
3968  // -----------------------------------
3969  Label miss_force_generic, grow, slow, transition_elements_kind;
3970  Label check_capacity, prepare_slow, finish_store, commit_backing_store;
3971 
3972  // This stub is meant to be tail-jumped to, the receiver must already
3973  // have been verified by the caller to not be a smi.
3974 
3975  // Check that the key is a smi or a heap number convertible to a smi.
3976  GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic);
3977 
3978  if (IsFastSmiElementsKind(elements_kind)) {
3979  __ JumpIfNotSmi(eax, &transition_elements_kind);
3980  }
3981 
3982  // Get the elements array and make sure it is a fast element array, not 'cow'.
3983  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3984  if (is_js_array) {
3985  // Check that the key is within bounds.
3986  __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
3987  if (grow_mode == ALLOW_JSARRAY_GROWTH) {
3988  __ j(above_equal, &grow);
3989  } else {
3990  __ j(above_equal, &miss_force_generic);
3991  }
3992  } else {
3993  // Check that the key is within bounds.
3994  __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
3995  __ j(above_equal, &miss_force_generic);
3996  }
3997 
3999  Immediate(masm->isolate()->factory()->fixed_array_map()));
4000  __ j(not_equal, &miss_force_generic);
4001 
4002  __ bind(&finish_store);
4003  if (IsFastSmiElementsKind(elements_kind)) {
4004  // ecx is a smi, use times_half_pointer_size instead of
4005  // times_pointer_size
4006  __ mov(FieldOperand(edi,
4007  ecx,
4009  FixedArray::kHeaderSize), eax);
4010  } else {
4011  ASSERT(IsFastObjectElementsKind(elements_kind));
4012  // Do the store and update the write barrier.
4013  // ecx is a smi, use times_half_pointer_size instead of
4014  // times_pointer_size
4015  __ lea(ecx, FieldOperand(edi,
4016  ecx,
4018  FixedArray::kHeaderSize));
4019  __ mov(Operand(ecx, 0), eax);
4020  // Make sure to preserve the value in register eax.
4021  __ mov(ebx, eax);
4022  __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs);
4023  }
4024 
4025  // Done.
4026  __ ret(0);
4027 
4028  // Handle store cache miss, replacing the ic with the generic stub.
4029  __ bind(&miss_force_generic);
4030  Handle<Code> ic_force_generic =
4031  masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4032  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
4033 
4034  // Handle transition to other elements kinds without using the generic stub.
4035  __ bind(&transition_elements_kind);
4036  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
4037  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
4038 
4039  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
4040  // Handle transition requiring the array to grow.
4041  __ bind(&grow);
4042 
4043  // Make sure the array is only growing by a single element, anything else
4044  // must be handled by the runtime. Flags are already set by previous
4045  // compare.
4046  __ j(not_equal, &miss_force_generic);
4047 
4048  // Check for the empty array, and preallocate a small backing store if
4049  // possible.
4050  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
4051  __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
4052  __ j(not_equal, &check_capacity);
4053 
4055  __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
4056  // Restore the key, which is known to be the array length.
4057 
4058  // eax: value
4059  // ecx: key
4060  // edx: receiver
4061  // edi: elements
4062  // Make sure that the backing store can hold additional elements.
4064  Immediate(masm->isolate()->factory()->fixed_array_map()));
4067  __ mov(ebx, Immediate(masm->isolate()->factory()->the_hole_value()));
4068  for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
4069  __ mov(FieldOperand(edi, FixedArray::SizeFor(i)), ebx);
4070  }
4071 
4072  // Store the element at index zero.
4073  __ mov(FieldOperand(edi, FixedArray::SizeFor(0)), eax);
4074 
4075  // Install the new backing store in the JSArray.
4076  __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
4077  __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
4079 
4080  // Increment the length of the array.
4082  Immediate(Smi::FromInt(1)));
4083  __ ret(0);
4084 
4085  __ bind(&check_capacity);
4087  Immediate(masm->isolate()->factory()->fixed_cow_array_map()));
4088  __ j(equal, &miss_force_generic);
4089 
4090  // eax: value
4091  // ecx: key
4092  // edx: receiver
4093  // edi: elements
4094  // Make sure that the backing store can hold additional elements.
4096  __ j(above_equal, &slow);
4097 
4098  // Grow the array and finish the store.
4100  Immediate(Smi::FromInt(1)));
4101  __ jmp(&finish_store);
4102 
4103  __ bind(&prepare_slow);
4104  // Restore the key, which is known to be the array length.
4105  __ mov(ecx, Immediate(0));
4106 
4107  __ bind(&slow);
4108  Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
4109  __ jmp(ic_slow, RelocInfo::CODE_TARGET);
4110  }
4111 }
4112 
4113 
4115  MacroAssembler* masm,
4116  bool is_js_array,
4117  KeyedAccessGrowMode grow_mode) {
4118  // ----------- S t a t e -------------
4119  // -- eax : value
4120  // -- ecx : key
4121  // -- edx : receiver
4122  // -- esp[0] : return address
4123  // -----------------------------------
4124  Label miss_force_generic, transition_elements_kind, grow, slow;
4125  Label check_capacity, prepare_slow, finish_store, commit_backing_store;
4126 
4127  // This stub is meant to be tail-jumped to, the receiver must already
4128  // have been verified by the caller to not be a smi.
4129 
4130  // Check that the key is a smi or a heap number convertible to a smi.
4131  GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic);
4132 
4133  // Get the elements array.
4134  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
4135  __ AssertFastElements(edi);
4136 
4137  if (is_js_array) {
4138  // Check that the key is within bounds.
4139  __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
4140  if (grow_mode == ALLOW_JSARRAY_GROWTH) {
4141  __ j(above_equal, &grow);
4142  } else {
4143  __ j(above_equal, &miss_force_generic);
4144  }
4145  } else {
4146  // Check that the key is within bounds.
4147  __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
4148  __ j(above_equal, &miss_force_generic);
4149  }
4150 
4151  __ bind(&finish_store);
4152  __ StoreNumberToDoubleElements(eax, edi, ecx, edx, xmm0,
4153  &transition_elements_kind, true);
4154  __ ret(0);
4155 
4156  // Handle store cache miss, replacing the ic with the generic stub.
4157  __ bind(&miss_force_generic);
4158  Handle<Code> ic_force_generic =
4159  masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4160  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
4161 
4162  // Handle transition to other elements kinds without using the generic stub.
4163  __ bind(&transition_elements_kind);
4164  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
4165  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
4166 
4167  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
4168  // Handle transition requiring the array to grow.
4169  __ bind(&grow);
4170 
4171  // Make sure the array is only growing by a single element, anything else
4172  // must be handled by the runtime. Flags are already set by previous
4173  // compare.
4174  __ j(not_equal, &miss_force_generic);
4175 
4176  // Transition on values that can't be stored in a FixedDoubleArray.
4177  Label value_is_smi;
4178  __ JumpIfSmi(eax, &value_is_smi);
4180  Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map())));
4181  __ j(not_equal, &transition_elements_kind);
4182  __ bind(&value_is_smi);
4183 
4184  // Check for the empty array, and preallocate a small backing store if
4185  // possible.
4186  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
4187  __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
4188  __ j(not_equal, &check_capacity);
4189 
4190  int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
4191  __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
4192 
4193  // Restore the key, which is known to be the array length.
4194  __ mov(ecx, Immediate(0));
4195 
4196  // eax: value
4197  // ecx: key
4198  // edx: receiver
4199  // edi: elements
4200  // Initialize the new FixedDoubleArray. Leave elements unitialized for
4201  // efficiency, they are guaranteed to be initialized before use.
4203  Immediate(masm->isolate()->factory()->fixed_double_array_map()));
4205  Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
4206 
4207  // Install the new backing store in the JSArray.
4208  __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
4209  __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
4211 
4212  // Increment the length of the array.
4214  Immediate(Smi::FromInt(1)));
4215  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
4216  __ jmp(&finish_store);
4217 
4218  __ bind(&check_capacity);
4219  // eax: value
4220  // ecx: key
4221  // edx: receiver
4222  // edi: elements
4223  // Make sure that the backing store can hold additional elements.
4225  __ j(above_equal, &slow);
4226 
4227  // Grow the array and finish the store.
4229  Immediate(Smi::FromInt(1)));
4230  __ jmp(&finish_store);
4231 
4232  __ bind(&prepare_slow);
4233  // Restore the key, which is known to be the array length.
4234  __ mov(ecx, Immediate(0));
4235 
4236  __ bind(&slow);
4237  Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
4238  __ jmp(ic_slow, RelocInfo::CODE_TARGET);
4239  }
4240 }
4241 
4242 
4243 #undef __
4244 
4245 } } // namespace v8::internal
4246 
4247 #endif // V8_TARGET_ARCH_IA32
byte * Address
Definition: globals.h:172
static const int kBitFieldOffset
Definition: objects.h:4994
Handle< Code > CompileLoadFunctionPrototype(Handle< String > name)
Handle< Code > CompileLoadCallback(Handle< String > name, Handle< JSObject > object, Handle< JSObject > holder, Handle< AccessorInfo > callback)
static const int kCodeEntryOffset
Definition: objects.h:5981
Handle< Code > CompileStoreField(Handle< JSObject > object, int index, Handle< Map > transition, Handle< String > name)
static const int kPrototypeOrInitialMapOffset
Definition: objects.h:5982
static int SlotOffset(int index)
Definition: contexts.h:408
static const int kDataOffset
Definition: objects.h:8190
Handle< Code > CompileLoadNonexistent(Handle< String > name, Handle< JSObject > object, Handle< JSObject > last)
Handle< Code > CompileStoreElement(Handle< Map > receiver_map)
void GenerateProbe(MacroAssembler *masm, Code::Flags flags, Register receiver, Register name, Register scratch, Register extra, Register extra2=no_reg, Register extra3=no_reg)
static const int kFlagsOffset
Definition: objects.h:4504
static Smi * FromInt(int value)
Definition: objects-inl.h:973
bool IsFastObjectElementsKind(ElementsKind kind)
#define LOG(isolate, Call)
Definition: log.h:81
static void GenerateStoreExternalArray(MacroAssembler *masm, ElementsKind elements_kind)
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
Definition: flags.cc:1349
const Register esp
Handle< Code > CompileStoreViaSetter(Handle< JSObject > receiver, Handle< JSFunction > setter, Handle< String > name)
static const int kGlobalReceiverOffset
Definition: objects.h:6085
static void GenerateLoadFastDoubleElement(MacroAssembler *masm)
static PropertyType ExtractTypeFromFlags(Flags flags)
Definition: objects-inl.h:3359
Flag flags[]
Definition: flags.cc:1467
static bool IsSupported(CpuFeature f)
static const int kExternalPointerOffset
Definition: objects.h:3720
static bool enabled()
Definition: serialize.h:480
static const int kHasNamedInterceptor
Definition: objects.h:5003
static const int kIsAccessCheckNeeded
Definition: objects.h:5007
List< Handle< Map > > MapHandleList
Definition: list.h:193
#define ASSERT(condition)
Definition: checks.h:270
Handle< Code > CompileStoreCallback(Handle< JSObject > object, Handle< AccessorInfo > callback, Handle< String > name)
const int kPointerSizeLog2
Definition: globals.h:246
static const int kInstanceSizeOffset
Definition: objects.h:4981
static const int kDebugInfoOffset
Definition: objects.h:5614
static const int kContextOffset
Definition: objects.h:5986
Handle< Code > CompileLoadField(Handle< JSObject > object, Handle< JSObject > holder, int index, Handle< String > name)
Handle< Code > CompileStoreInterceptor(Handle< JSObject > object, Handle< String > name)
static void GenerateNegativeLookup(MacroAssembler *masm, Label *miss, Label *done, Register receiver, Register properties, Handle< String > name, Register scratch0)
Handle< Code > CompileStoreField(Handle< JSObject > object, int index, Handle< Map > transition, Handle< String > name)
const Register edi
static const int kHashFieldOffset
Definition: objects.h:7099
const uint32_t kNotStringTag
Definition: objects.h:438
Handle< Code > CompileLoadInterceptor(Handle< JSObject > object, Handle< JSObject > holder, Handle< String > name)
const Register ebp
#define UNREACHABLE()
Definition: checks.h:50
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static const int kLengthOffset
Definition: objects.h:7098
Handle< Code > CompileCallGlobal(Handle< JSObject > object, Handle< GlobalObject > holder, Handle< JSGlobalPropertyCell > cell, Handle< JSFunction > function, Handle< String > name)
const Register eax
Handle< Code > CompileLoadField(Handle< String > name, Handle< JSObject > object, Handle< JSObject > holder, int index)
static const int kValueOffset
Definition: objects.h:1307
const uint32_t kHoleNanUpper32
Definition: v8globals.h:476
Handle< Code > CompileStoreGlobal(Handle< GlobalObject > object, Handle< JSGlobalPropertyCell > holder, Handle< String > name)
Handle< Code > CompileLoadViaGetter(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > getter)
Handle< Code > CompileLoadConstant(Handle< JSObject > object, Handle< JSObject > holder, Handle< JSFunction > value, Handle< String > name)
const XMMRegister xmm1
Handle< Code > CompileLoadConstant(Handle< String > name, Handle< JSObject > object, Handle< JSObject > holder, Handle< JSFunction > value)
Handle< Code > CompileCallField(Handle< JSObject > object, Handle< JSObject > holder, int index, Handle< String > name)
const int kPointerSize
Definition: globals.h:234
static void GenerateStoreFastElement(MacroAssembler *masm, bool is_js_array, ElementsKind element_kind, KeyedAccessGrowMode grow_mode)
Handle< Code > CompileLoadStringLength(Handle< String > name)
Operand FieldOperand(Register object, int offset)
const Register ecx
const Address kZapValue
Definition: v8globals.h:89
const int kHeapObjectTag
Definition: v8.h:3848
const uint32_t kHoleNanLower32
Definition: v8globals.h:477
#define __
static bool decode(uint32_t value)
Definition: utils.h:272
static const int kPropertiesOffset
Definition: objects.h:2113
Handle< Code > CompileLoadGlobal(Handle< JSObject > object, Handle< GlobalObject > holder, Handle< JSGlobalPropertyCell > cell, Handle< String > name, bool is_dont_delete)
bool IsFastSmiElementsKind(ElementsKind kind)
static void GenerateMapChangeElementsTransition(MacroAssembler *masm)
static const int kDataOffset
Definition: objects.h:8326
static int SizeFor(int length)
Definition: objects.h:2369
const Register r0
static const int kElementsOffset
Definition: objects.h:2114
#define BASE_EMBEDDED
Definition: allocation.h:68
const int kBitsPerInt
Definition: globals.h:254
static void GenerateLoadDictionaryElement(MacroAssembler *masm)
static void GenerateLoadExternalArray(MacroAssembler *masm, ElementsKind elements_kind)
static const int kLengthOffset
Definition: objects.h:8111
static int SizeFor(int length)
Definition: objects.h:2288
static const int kHeaderSize
Definition: objects.h:2233
static const int kMapOffset
Definition: objects.h:1219
List< Handle< Code > > CodeHandleList
Definition: list.h:194
const Register r1
static const int kLengthOffset
Definition: objects.h:2232
const Register ebx
Handle< Code > CompileCallInterceptor(Handle< JSObject > object, Handle< JSObject > holder, Handle< String > name)
static const int kDataOffset
Definition: objects.h:8352
static void GenerateLoadFastElement(MacroAssembler *masm)
static const uint32_t kSignMask
Definition: objects.h:1316
Operand ApiParameterOperand(int index)
const int kSmiTagSize
Definition: v8.h:3854
static void GenerateStoreFastDoubleElement(MacroAssembler *masm, bool is_js_array, KeyedAccessGrowMode grow_mode)
static const int kHeaderSize
Definition: objects.h:4513
static Handle< T > null()
Definition: handles.h:86
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
const Register esi
Handle< Code > CompileLoadArrayLength(Handle< String > name)
const int kSmiTag
Definition: v8.h:3853
Handle< Code > CompileCallConstant(Handle< Object > object, Handle< JSObject > holder, Handle< JSFunction > function, Handle< String > name, CheckType check)
static AccessorInfo * cast(Object *obj)
static const int kHeaderSize
Definition: objects.h:2115
const int kHeapObjectTagSize
Definition: v8.h:3849
static Handle< JSGlobalPropertyCell > EnsurePropertyCell(Handle< GlobalObject > global, Handle< String > name)
Definition: objects.cc:11797
static bool HasCustomCallGenerator(Handle< JSFunction > function)
Definition: stub-cache.cc:1428
static const int kPreallocatedArrayElements
Definition: objects.h:8108
static const int kPrototypeOffset
Definition: objects.h:4953
static const int kFlagsNotUsedInLookup
Definition: objects.h:4557
const char * name_
Definition: flags.cc:1352
const int kInvalidProtoDepth
const Register no_reg
static const int kValueOffset
Definition: objects.h:6188
Handle< Code > CompileLoadCallback(Handle< String > name, Handle< JSObject > object, Handle< JSObject > holder, Handle< AccessorInfo > callback)
const XMMRegister xmm2
const Register edx
Handle< Code > CompileLoadPolymorphic(MapHandleList *receiver_maps, CodeHandleList *handler_ics)
Handle< Code > CompileLoadInterceptor(Handle< JSObject > object, Handle< JSObject > holder, Handle< String > name)
Handle< Code > CompileStorePolymorphic(MapHandleList *receiver_maps, CodeHandleList *handler_stubs, MapHandleList *transitioned_maps)
static const int kSharedFunctionInfoOffset
Definition: objects.h:5984
KeyedAccessGrowMode
Definition: objects.h:141
static const int kMantissaBits
Definition: objects.h:1319
void check(i::Vector< const char > string)
static const int kExponentOffset
Definition: objects.h:1313
Handle< Code > CompileLoadElement(Handle< Map > receiver_map)
Handle< Code > CompileConstructStub(Handle< JSFunction > function)
static JSObject * cast(Object *obj)
static const int kInstanceTypeOffset
Definition: objects.h:4992
static const int kMantissaOffset
Definition: objects.h:1312
const XMMRegister xmm0
static JSFunction * cast(Object *obj)