1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#if V8_TARGET_ARCH_X64
6
7#include "src/ic/handler-compiler.h"
8
9#include "src/api-arguments.h"
10#include "src/field-type.h"
11#include "src/ic/call-optimization.h"
12#include "src/ic/ic.h"
13#include "src/isolate-inl.h"
14
15namespace v8 {
16namespace internal {
17
18#define __ ACCESS_MASM(masm)
19
20void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
21                                                Register slot) {
22  MacroAssembler* masm = this->masm();
23  STATIC_ASSERT(LoadWithVectorDescriptor::kSlot <
24                LoadWithVectorDescriptor::kVector);
25  STATIC_ASSERT(StoreWithVectorDescriptor::kSlot <
26                StoreWithVectorDescriptor::kVector);
27  STATIC_ASSERT(StoreTransitionDescriptor::kSlot <
28                StoreTransitionDescriptor::kVector);
29  __ Push(slot);
30  __ Push(vector);
31}
32
33
34void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
35  MacroAssembler* masm = this->masm();
36  __ Pop(vector);
37  __ Pop(slot);
38}
39
40
41void PropertyHandlerCompiler::DiscardVectorAndSlot() {
42  MacroAssembler* masm = this->masm();
43  // Remove vector and slot.
44  __ addp(rsp, Immediate(2 * kPointerSize));
45}
46
47void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
48    MacroAssembler* masm, Label* miss_label, Register receiver,
49    Handle<Name> name, Register scratch0, Register scratch1) {
50  DCHECK(name->IsUniqueName());
51  DCHECK(!receiver.is(scratch0));
52  Counters* counters = masm->isolate()->counters();
53  __ IncrementCounter(counters->negative_lookups(), 1);
54  __ IncrementCounter(counters->negative_lookups_miss(), 1);
55
56  __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
57
58  const int kInterceptorOrAccessCheckNeededMask =
59      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
60
61  // Bail out if the receiver has a named interceptor or requires access checks.
62  __ testb(FieldOperand(scratch0, Map::kBitFieldOffset),
63           Immediate(kInterceptorOrAccessCheckNeededMask));
64  __ j(not_zero, miss_label);
65
66  // Check that receiver is a JSObject.
67  __ CmpInstanceType(scratch0, FIRST_JS_RECEIVER_TYPE);
68  __ j(below, miss_label);
69
70  // Load properties array.
71  Register properties = scratch0;
72  __ movp(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
73
74  // Check that the properties array is a dictionary.
75  __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
76                 Heap::kHashTableMapRootIndex);
77  __ j(not_equal, miss_label);
78
79  Label done;
80  NameDictionaryLookupStub::GenerateNegativeLookup(masm, miss_label, &done,
81                                                   properties, name, scratch1);
82  __ bind(&done);
83  __ DecrementCounter(counters->negative_lookups_miss(), 1);
84}
85
86static void CompileCallLoadPropertyWithInterceptor(
87    MacroAssembler* masm, Register receiver, Register holder, Register name,
88    Handle<JSObject> holder_obj, Runtime::FunctionId id) {
89  DCHECK(NamedLoadHandlerCompiler::kInterceptorArgsLength ==
90         Runtime::FunctionForId(id)->nargs);
91
92  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
93  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1);
94  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2);
95  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3);
96  __ Push(name);
97  __ Push(receiver);
98  __ Push(holder);
99
100  __ CallRuntime(id);
101}
102
103
104// Generate call to api function.
105void PropertyHandlerCompiler::GenerateApiAccessorCall(
106    MacroAssembler* masm, const CallOptimization& optimization,
107    Handle<Map> receiver_map, Register receiver, Register scratch,
108    bool is_store, Register store_parameter, Register accessor_holder,
109    int accessor_index) {
110  DCHECK(!accessor_holder.is(scratch));
111  DCHECK(optimization.is_simple_api_call());
112
113  __ PopReturnAddressTo(scratch);
114  // receiver
115  __ Push(receiver);
116  // Write the arguments to stack frame.
117  if (is_store) {
118    DCHECK(!receiver.is(store_parameter));
119    DCHECK(!scratch.is(store_parameter));
120    __ Push(store_parameter);
121  }
122  __ PushReturnAddressFrom(scratch);
123  // Stack now matches JSFunction abi.
124
125  // Abi for CallApiCallbackStub.
126  Register callee = rdi;
127  Register data = rbx;
128  Register holder = rcx;
129  Register api_function_address = rdx;
130  scratch = no_reg;
131
132  // Put callee in place.
133  __ LoadAccessor(callee, accessor_holder, accessor_index,
134                  is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER);
135
136  // Put holder in place.
137  CallOptimization::HolderLookup holder_lookup;
138  int holder_depth = 0;
139  optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup,
140                                          &holder_depth);
141  switch (holder_lookup) {
142    case CallOptimization::kHolderIsReceiver:
143      __ Move(holder, receiver);
144      break;
145    case CallOptimization::kHolderFound:
146      __ movp(holder, FieldOperand(receiver, HeapObject::kMapOffset));
147      __ movp(holder, FieldOperand(holder, Map::kPrototypeOffset));
148      for (int i = 1; i < holder_depth; i++) {
149        __ movp(holder, FieldOperand(holder, HeapObject::kMapOffset));
150        __ movp(holder, FieldOperand(holder, Map::kPrototypeOffset));
151      }
152      break;
153    case CallOptimization::kHolderNotFound:
154      UNREACHABLE();
155      break;
156  }
157
158  Isolate* isolate = masm->isolate();
159  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
160  bool call_data_undefined = false;
161  // Put call data in place.
162  if (api_call_info->data()->IsUndefined(isolate)) {
163    call_data_undefined = true;
164    __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
165  } else {
166    if (optimization.is_constant_call()) {
167      __ movp(data,
168              FieldOperand(callee, JSFunction::kSharedFunctionInfoOffset));
169      __ movp(data,
170              FieldOperand(data, SharedFunctionInfo::kFunctionDataOffset));
171      __ movp(data, FieldOperand(data, FunctionTemplateInfo::kCallCodeOffset));
172    } else {
173      __ movp(data,
174              FieldOperand(callee, FunctionTemplateInfo::kCallCodeOffset));
175    }
176    __ movp(data, FieldOperand(data, CallHandlerInfo::kDataOffset));
177  }
178
179  if (api_call_info->fast_handler()->IsCode()) {
180    // Just tail call into the fast handler if present.
181    __ Jump(handle(Code::cast(api_call_info->fast_handler())),
182            RelocInfo::CODE_TARGET);
183    return;
184  }
185
186  // Put api_function_address in place.
187  Address function_address = v8::ToCData<Address>(api_call_info->callback());
188  __ Move(api_function_address, function_address,
189          RelocInfo::EXTERNAL_REFERENCE);
190
191  // Jump to stub.
192  CallApiCallbackStub stub(isolate, is_store, call_data_undefined,
193                           !optimization.is_constant_call());
194  __ TailCallStub(&stub);
195}
196
197
198void PropertyHandlerCompiler::GenerateCheckPropertyCell(
199    MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
200    Register scratch, Label* miss) {
201  Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
202      global, name, PropertyCellType::kInvalidated);
203  Isolate* isolate = masm->isolate();
204  DCHECK(cell->value()->IsTheHole(isolate));
205  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
206  __ LoadWeakValue(scratch, weak_cell, miss);
207  __ Cmp(FieldOperand(scratch, PropertyCell::kValueOffset),
208         isolate->factory()->the_hole_value());
209  __ j(not_equal, miss);
210}
211
212
213void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
214    MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
215    int accessor_index, int expected_arguments, Register scratch) {
216  // ----------- S t a t e -------------
217  //  -- rsp[0] : return address
218  // -----------------------------------
219  {
220    FrameScope scope(masm, StackFrame::INTERNAL);
221
222    // Save context register
223    __ pushq(rsi);
224    // Save value register, so we can restore it later.
225    __ Push(value());
226
227    if (accessor_index >= 0) {
228      DCHECK(!holder.is(scratch));
229      DCHECK(!receiver.is(scratch));
230      DCHECK(!value().is(scratch));
231      // Call the JavaScript setter with receiver and value on the stack.
232      if (map->IsJSGlobalObjectMap()) {
233        // Swap in the global receiver.
234        __ movp(scratch,
235                FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
236        receiver = scratch;
237      }
238      __ Push(receiver);
239      __ Push(value());
240      __ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_SETTER);
241      __ Set(rax, 1);
242      __ Call(masm->isolate()->builtins()->CallFunction(
243                  ConvertReceiverMode::kNotNullOrUndefined),
244              RelocInfo::CODE_TARGET);
245    } else {
246      // If we generate a global code snippet for deoptimization only, remember
247      // the place to continue after deoptimization.
248      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
249    }
250
251    // We have to return the passed value, not the return value of the setter.
252    __ Pop(rax);
253
254    // Restore context register.
255    __ popq(rsi);
256  }
257  __ ret(0);
258}
259
260
261void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
262    MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
263    int accessor_index, int expected_arguments, Register scratch) {
264  // ----------- S t a t e -------------
265  //  -- rax    : receiver
266  //  -- rcx    : name
267  //  -- rsp[0] : return address
268  // -----------------------------------
269  {
270    FrameScope scope(masm, StackFrame::INTERNAL);
271
272    // Save context register
273    __ pushq(rsi);
274
275    if (accessor_index >= 0) {
276      DCHECK(!holder.is(scratch));
277      DCHECK(!receiver.is(scratch));
278      // Call the JavaScript getter with the receiver on the stack.
279      if (map->IsJSGlobalObjectMap()) {
280        // Swap in the global receiver.
281        __ movp(scratch,
282                FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
283        receiver = scratch;
284      }
285      __ Push(receiver);
286      __ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_GETTER);
287      __ Set(rax, 0);
288      __ Call(masm->isolate()->builtins()->CallFunction(
289                  ConvertReceiverMode::kNotNullOrUndefined),
290              RelocInfo::CODE_TARGET);
291    } else {
292      // If we generate a global code snippet for deoptimization only, remember
293      // the place to continue after deoptimization.
294      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
295    }
296
297    // Restore context register.
298    __ popq(rsi);
299  }
300  __ ret(0);
301}
302
303#undef __
304#define __ ACCESS_MASM((masm()))
305
306
307void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
308                                                    Handle<Name> name) {
309  if (!label->is_unused()) {
310    __ bind(label);
311    __ Move(this->name(), name);
312  }
313}
314
315void PropertyHandlerCompiler::GenerateAccessCheck(
316    Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
317    Label* miss, bool compare_native_contexts_only) {
318  Label done;
319  // Load current native context.
320  __ movp(scratch1, NativeContextOperand());
321  // Load expected native context.
322  __ LoadWeakValue(scratch2, native_context_cell, miss);
323  __ cmpp(scratch1, scratch2);
324
325  if (!compare_native_contexts_only) {
326    __ j(equal, &done);
327
328    // Compare security tokens of current and expected native contexts.
329    __ movp(scratch1, ContextOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
330    __ movp(scratch2, ContextOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
331    __ cmpp(scratch1, scratch2);
332  }
333  __ j(not_equal, miss);
334
335  __ bind(&done);
336}
337
338Register PropertyHandlerCompiler::CheckPrototypes(
339    Register object_reg, Register holder_reg, Register scratch1,
340    Register scratch2, Handle<Name> name, Label* miss,
341    ReturnHolder return_what) {
342  Handle<Map> receiver_map = map();
343
344  // Make sure there's no overlap between holder and object registers.
345  DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
346  DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
347         !scratch2.is(scratch1));
348
349  Handle<Cell> validity_cell =
350      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
351  if (!validity_cell.is_null()) {
352    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
353    __ Move(scratch1, validity_cell, RelocInfo::CELL);
354    // Move(..., CELL) loads the payload's address!
355    __ SmiCompare(Operand(scratch1, 0),
356                  Smi::FromInt(Map::kPrototypeChainValid));
357    __ j(not_equal, miss);
358  }
359
360  // Keep track of the current object in register reg.  On the first
361  // iteration, reg is an alias for object_reg, on later iterations,
362  // it is an alias for holder_reg.
363  Register reg = object_reg;
364  int depth = 0;
365
366  Handle<JSObject> current = Handle<JSObject>::null();
367  if (receiver_map->IsJSGlobalObjectMap()) {
368    current = isolate()->global_object();
369  }
370
371  Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
372                          isolate());
373  Handle<Map> holder_map(holder()->map());
374  // Traverse the prototype chain and check the maps in the prototype chain for
375  // fast and global objects or do negative lookup for normal objects.
376  while (!current_map.is_identical_to(holder_map)) {
377    ++depth;
378
379    if (current_map->IsJSGlobalObjectMap()) {
380      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
381                                name, scratch2, miss);
382    } else if (current_map->is_dictionary_map()) {
383      DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
384      DCHECK(name->IsUniqueName());
385      DCHECK(current.is_null() ||
386             current->property_dictionary()->FindEntry(name) ==
387                 NameDictionary::kNotFound);
388
389      if (depth > 1) {
390        Handle<WeakCell> weak_cell =
391            Map::GetOrCreatePrototypeWeakCell(current, isolate());
392        __ LoadWeakValue(reg, weak_cell, miss);
393      }
394      GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
395                                       scratch2);
396    }
397
398    reg = holder_reg;  // From now on the object will be in holder_reg.
399    // Go to the next object in the prototype chain.
400    current = handle(JSObject::cast(current_map->prototype()));
401    current_map = handle(current->map());
402  }
403
404  DCHECK(!current_map->IsJSGlobalProxyMap());
405
406  // Log the check depth.
407  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
408
409  bool return_holder = return_what == RETURN_HOLDER;
410  if (return_holder && depth != 0) {
411    Handle<WeakCell> weak_cell =
412        Map::GetOrCreatePrototypeWeakCell(current, isolate());
413    __ LoadWeakValue(reg, weak_cell, miss);
414  }
415
416  // Return the register containing the holder.
417  return return_holder ? reg : no_reg;
418}
419
420
421void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
422  if (!miss->is_unused()) {
423    Label success;
424    __ jmp(&success);
425    __ bind(miss);
426    if (IC::ICUseVector(kind())) {
427      DCHECK(kind() == Code::LOAD_IC);
428      PopVectorAndSlot();
429    }
430    TailCallBuiltin(masm(), MissBuiltin(kind()));
431    __ bind(&success);
432  }
433}
434
435
436void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
437  if (!miss->is_unused()) {
438    Label success;
439    __ jmp(&success);
440    GenerateRestoreName(miss, name);
441    if (IC::ICUseVector(kind())) PopVectorAndSlot();
442    TailCallBuiltin(masm(), MissBuiltin(kind()));
443    __ bind(&success);
444  }
445}
446
447void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
448    LookupIterator* it, Register holder_reg) {
449  DCHECK(holder()->HasNamedInterceptor());
450  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
451
452  // Compile the interceptor call, followed by inline code to load the
453  // property from further up the prototype chain if the call fails.
454  // Check that the maps haven't changed.
455  DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
456
457  // Preserve the receiver register explicitly whenever it is different from the
458  // holder and it is needed should the interceptor return without any result.
459  // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD
460  // case might cause a miss during the prototype check.
461  bool must_perform_prototype_check =
462      !holder().is_identical_to(it->GetHolder<JSObject>());
463  bool must_preserve_receiver_reg =
464      !receiver().is(holder_reg) &&
465      (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check);
466
467  // Save necessary data before invoking an interceptor.
468  // Requires a frame to make GC aware of pushed pointers.
469  {
470    FrameScope frame_scope(masm(), StackFrame::INTERNAL);
471
472    if (must_preserve_receiver_reg) {
473      __ Push(receiver());
474    }
475    __ Push(holder_reg);
476    __ Push(this->name());
477    InterceptorVectorSlotPush(holder_reg);
478
479    // Invoke an interceptor.  Note: map checks from receiver to
480    // interceptor's holder has been compiled before (see a caller
481    // of this method.)
482    CompileCallLoadPropertyWithInterceptor(
483        masm(), receiver(), holder_reg, this->name(), holder(),
484        Runtime::kLoadPropertyWithInterceptorOnly);
485
486    // Check if interceptor provided a value for property.  If it's
487    // the case, return immediately.
488    Label interceptor_failed;
489    __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
490    __ j(equal, &interceptor_failed);
491    frame_scope.GenerateLeaveFrame();
492    __ ret(0);
493
494    __ bind(&interceptor_failed);
495    InterceptorVectorSlotPop(holder_reg);
496    __ Pop(this->name());
497    __ Pop(holder_reg);
498    if (must_preserve_receiver_reg) {
499      __ Pop(receiver());
500    }
501
502    // Leave the internal frame.
503  }
504
505  GenerateLoadPostInterceptor(it, holder_reg);
506}
507
508
509void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
510  // Call the runtime system to load the interceptor.
511  DCHECK(holder()->HasNamedInterceptor());
512  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
513
514  // Stack:
515  //   return address
516
517  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
518  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1);
519  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2);
520  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3);
521  __ Push(receiver());
522  __ Push(holder_reg);
523  // See NamedLoadHandlerCompiler::InterceptorVectorSlotPop() for details.
524  if (holder_reg.is(receiver())) {
525    __ Push(slot());
526    __ Push(vector());
527  } else {
528    __ Push(scratch3());  // slot
529    __ Push(scratch2());  // vector
530  }
531  __ Push(Operand(rsp, 4 * kPointerSize));  // return address
532  __ movp(Operand(rsp, 5 * kPointerSize), name());
533
534  __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
535}
536
537void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() {
538  STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack);
539}
540
541Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
542    Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
543    LanguageMode language_mode) {
544  Register holder_reg = Frontend(name);
545
546  __ PopReturnAddressTo(scratch1());
547  __ Push(receiver());
548  __ Push(holder_reg);
549  // If the callback cannot leak, then push the callback directly,
550  // otherwise wrap it in a weak cell.
551  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
552    __ Push(callback);
553  } else {
554    Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
555    __ Push(cell);
556  }
557  __ Push(name);
558  __ Push(value());
559  __ Push(Smi::FromInt(language_mode));
560  __ PushReturnAddressFrom(scratch1());
561
562  // Do tail-call to the runtime system.
563  __ TailCallRuntime(Runtime::kStoreCallbackProperty);
564
565  // Return the generated code.
566  return GetCode(kind(), name);
567}
568
569
570Register NamedStoreHandlerCompiler::value() {
571  return StoreDescriptor::ValueRegister();
572}
573
574
575Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
576    Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
577  Label miss;
578  if (IC::ICUseVector(kind())) {
579    PushVectorAndSlot();
580  }
581  FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING);
582
583  // Get the value from the cell.
584  Register result = StoreDescriptor::ValueRegister();
585  Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
586  __ LoadWeakValue(result, weak_cell, &miss);
587  __ movp(result, FieldOperand(result, PropertyCell::kValueOffset));
588
589  // Check for deleted property if property can actually be deleted.
590  if (is_configurable) {
591    __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
592    __ j(equal, &miss);
593  } else if (FLAG_debug_code) {
594    __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
595    __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
596  }
597
598  Counters* counters = isolate()->counters();
599  __ IncrementCounter(counters->ic_named_load_global_stub(), 1);
600  if (IC::ICUseVector(kind())) {
601    DiscardVectorAndSlot();
602  }
603  __ ret(0);
604
605  FrontendFooter(name, &miss);
606
607  // Return the generated code.
608  return GetCode(kind(), name);
609}
610
611
612#undef __
613}  // namespace internal
614}  // namespace v8
615
616#endif  // V8_TARGET_ARCH_X64
617