1// Copyright 2012 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#include "src/v8.h"
6
7#if V8_TARGET_ARCH_X87
8
9#include "src/ic/ic.h"
10#include "src/ic/ic-compiler.h"
11
12namespace v8 {
13namespace internal {
14
15#define __ ACCESS_MASM(masm)
16
17
18void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm,
19                                                    StrictMode strict_mode) {
20  // Return address is on the stack.
21  DCHECK(!ebx.is(StoreDescriptor::ReceiverRegister()) &&
22         !ebx.is(StoreDescriptor::NameRegister()) &&
23         !ebx.is(StoreDescriptor::ValueRegister()));
24  __ pop(ebx);
25  __ push(StoreDescriptor::ReceiverRegister());
26  __ push(StoreDescriptor::NameRegister());
27  __ push(StoreDescriptor::ValueRegister());
28  __ push(Immediate(Smi::FromInt(strict_mode)));
29  __ push(ebx);  // return address
30
31  // Do tail-call to runtime routine.
32  __ TailCallRuntime(Runtime::kSetProperty, 4, 1);
33}
34
35
36#undef __
37#define __ ACCESS_MASM(masm())
38
39Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
40                                                    CodeHandleList* handlers,
41                                                    Handle<Name> name,
42                                                    Code::StubType type,
43                                                    IcCheckType check) {
44  Label miss;
45
46  if (check == PROPERTY &&
47      (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
48    // In case we are compiling an IC for dictionary loads and stores, just
49    // check whether the name is unique.
50    if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) {
51      Register tmp = scratch1();
52      __ JumpIfSmi(this->name(), &miss);
53      __ mov(tmp, FieldOperand(this->name(), HeapObject::kMapOffset));
54      __ movzx_b(tmp, FieldOperand(tmp, Map::kInstanceTypeOffset));
55      __ JumpIfNotUniqueNameInstanceType(tmp, &miss);
56    } else {
57      __ cmp(this->name(), Immediate(name));
58      __ j(not_equal, &miss);
59    }
60  }
61
62  Label number_case;
63  Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
64  __ JumpIfSmi(receiver(), smi_target);
65
66  // Polymorphic keyed stores may use the map register
67  Register map_reg = scratch1();
68  DCHECK(kind() != Code::KEYED_STORE_IC ||
69         map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister()));
70  __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
71  int receiver_count = types->length();
72  int number_of_handled_maps = 0;
73  for (int current = 0; current < receiver_count; ++current) {
74    Handle<HeapType> type = types->at(current);
75    Handle<Map> map = IC::TypeToMap(*type, isolate());
76    if (!map->is_deprecated()) {
77      number_of_handled_maps++;
78      __ cmp(map_reg, map);
79      if (type->Is(HeapType::Number())) {
80        DCHECK(!number_case.is_unused());
81        __ bind(&number_case);
82      }
83      __ j(equal, handlers->at(current));
84    }
85  }
86  DCHECK(number_of_handled_maps != 0);
87
88  __ bind(&miss);
89  TailCallBuiltin(masm(), MissBuiltin(kind()));
90
91  // Return the generated code.
92  InlineCacheState state =
93      number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
94  return GetCode(kind(), type, name, state);
95}
96
97
98Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
99    MapHandleList* receiver_maps, CodeHandleList* handler_stubs,
100    MapHandleList* transitioned_maps) {
101  Label miss;
102  __ JumpIfSmi(receiver(), &miss, Label::kNear);
103  __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
104  for (int i = 0; i < receiver_maps->length(); ++i) {
105    __ cmp(scratch1(), receiver_maps->at(i));
106    if (transitioned_maps->at(i).is_null()) {
107      __ j(equal, handler_stubs->at(i));
108    } else {
109      Label next_map;
110      __ j(not_equal, &next_map, Label::kNear);
111      __ mov(transition_map(), Immediate(transitioned_maps->at(i)));
112      __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
113      __ bind(&next_map);
114    }
115  }
116  __ bind(&miss);
117  TailCallBuiltin(masm(), MissBuiltin(kind()));
118
119  // Return the generated code.
120  return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
121}
122
123
124#undef __
125}
126}  // namespace v8::internal
127
128#endif  // V8_TARGET_ARCH_X87
129