• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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/compiler/fast-accessor-assembler.h"
6 
7 #include "src/base/logging.h"
8 #include "src/compiler/graph.h"
9 #include "src/compiler/linkage.h"
10 #include "src/compiler/pipeline.h"
11 #include "src/compiler/raw-machine-assembler.h"
12 #include "src/compiler/schedule.h"
13 #include "src/compiler/verifier.h"
14 #include "src/handles-inl.h"
15 #include "src/objects.h"  // For FAA::GetInternalField impl.
16 
17 namespace v8 {
18 namespace internal {
19 namespace compiler {
20 
FastAccessorAssembler(Isolate * isolate)21 FastAccessorAssembler::FastAccessorAssembler(Isolate* isolate)
22     : zone_(),
23       assembler_(new RawMachineAssembler(
24           isolate, new (zone()) Graph(zone()),
25           Linkage::GetJSCallDescriptor(&zone_, false, 1,
26                                        CallDescriptor::kNoFlags))),
27       state_(kBuilding) {}
28 
29 
~FastAccessorAssembler()30 FastAccessorAssembler::~FastAccessorAssembler() {}
31 
32 
IntegerConstant(int const_value)33 FastAccessorAssembler::ValueId FastAccessorAssembler::IntegerConstant(
34     int const_value) {
35   CHECK_EQ(kBuilding, state_);
36   return FromRaw(assembler_->NumberConstant(const_value));
37 }
38 
39 
GetReceiver()40 FastAccessorAssembler::ValueId FastAccessorAssembler::GetReceiver() {
41   CHECK_EQ(kBuilding, state_);
42 
43   // For JS call descriptor, the receiver is parameter 0. If we use other
44   // call descriptors, this may or may not hold. So let's check.
45   CHECK(assembler_->call_descriptor()->IsJSFunctionCall());
46   return FromRaw(assembler_->Parameter(0));
47 }
48 
49 
LoadInternalField(ValueId value,int field_no)50 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadInternalField(
51     ValueId value, int field_no) {
52   CHECK_EQ(kBuilding, state_);
53   // Determine the 'value' object's instance type.
54   Node* object_map =
55       assembler_->Load(MachineType::Pointer(), FromId(value),
56                        assembler_->IntPtrConstant(
57                            Internals::kHeapObjectMapOffset - kHeapObjectTag));
58   Node* instance_type = assembler_->WordAnd(
59       assembler_->Load(
60           MachineType::Uint16(), object_map,
61           assembler_->IntPtrConstant(
62               Internals::kMapInstanceTypeAndBitFieldOffset - kHeapObjectTag)),
63       assembler_->IntPtrConstant(0xff));
64 
65   // Check whether we have a proper JSObject.
66   RawMachineLabel is_jsobject, is_not_jsobject, merge;
67   assembler_->Branch(
68       assembler_->WordEqual(
69           instance_type, assembler_->IntPtrConstant(Internals::kJSObjectType)),
70       &is_jsobject, &is_not_jsobject);
71 
72   // JSObject? Then load the internal field field_no.
73   assembler_->Bind(&is_jsobject);
74   Node* internal_field = assembler_->Load(
75       MachineType::Pointer(), FromId(value),
76       assembler_->IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag +
77                                  kPointerSize * field_no));
78   assembler_->Goto(&merge);
79 
80   // No JSObject? Return undefined.
81   // TODO(vogelheim): Check whether this is the appropriate action, or whether
82   //                  the method should take a label instead.
83   assembler_->Bind(&is_not_jsobject);
84   Node* fail_value = assembler_->UndefinedConstant();
85   assembler_->Goto(&merge);
86 
87   // Return.
88   assembler_->Bind(&merge);
89   Node* phi = assembler_->Phi(MachineRepresentation::kTagged, internal_field,
90                               fail_value);
91   return FromRaw(phi);
92 }
93 
94 
LoadValue(ValueId value,int offset)95 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadValue(ValueId value,
96                                                                 int offset) {
97   CHECK_EQ(kBuilding, state_);
98   return FromRaw(assembler_->Load(MachineType::IntPtr(), FromId(value),
99                                   assembler_->IntPtrConstant(offset)));
100 }
101 
102 
LoadObject(ValueId value,int offset)103 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadObject(ValueId value,
104                                                                  int offset) {
105   CHECK_EQ(kBuilding, state_);
106   return FromRaw(
107       assembler_->Load(MachineType::AnyTagged(),
108                        assembler_->Load(MachineType::Pointer(), FromId(value),
109                                         assembler_->IntPtrConstant(offset))));
110 }
111 
112 
ReturnValue(ValueId value)113 void FastAccessorAssembler::ReturnValue(ValueId value) {
114   CHECK_EQ(kBuilding, state_);
115   assembler_->Return(FromId(value));
116 }
117 
118 
CheckFlagSetOrReturnNull(ValueId value,int mask)119 void FastAccessorAssembler::CheckFlagSetOrReturnNull(ValueId value, int mask) {
120   CHECK_EQ(kBuilding, state_);
121   RawMachineLabel pass, fail;
122   assembler_->Branch(
123       assembler_->Word32Equal(
124           assembler_->Word32And(FromId(value), assembler_->Int32Constant(mask)),
125           assembler_->Int32Constant(0)),
126       &pass, &fail);
127   assembler_->Bind(&fail);
128   assembler_->Return(assembler_->NullConstant());
129   assembler_->Bind(&pass);
130 }
131 
132 
CheckNotZeroOrReturnNull(ValueId value)133 void FastAccessorAssembler::CheckNotZeroOrReturnNull(ValueId value) {
134   CHECK_EQ(kBuilding, state_);
135   RawMachineLabel is_null, not_null;
136   assembler_->Branch(
137       assembler_->IntPtrEqual(FromId(value), assembler_->IntPtrConstant(0)),
138       &is_null, &not_null);
139   assembler_->Bind(&is_null);
140   assembler_->Return(assembler_->NullConstant());
141   assembler_->Bind(&not_null);
142 }
143 
144 
MakeLabel()145 FastAccessorAssembler::LabelId FastAccessorAssembler::MakeLabel() {
146   CHECK_EQ(kBuilding, state_);
147   RawMachineLabel* label =
148       new (zone()->New(sizeof(RawMachineLabel))) RawMachineLabel;
149   return FromRaw(label);
150 }
151 
152 
SetLabel(LabelId label_id)153 void FastAccessorAssembler::SetLabel(LabelId label_id) {
154   CHECK_EQ(kBuilding, state_);
155   assembler_->Bind(FromId(label_id));
156 }
157 
158 
CheckNotZeroOrJump(ValueId value_id,LabelId label_id)159 void FastAccessorAssembler::CheckNotZeroOrJump(ValueId value_id,
160                                                LabelId label_id) {
161   CHECK_EQ(kBuilding, state_);
162   RawMachineLabel pass;
163   assembler_->Branch(
164       assembler_->IntPtrEqual(FromId(value_id), assembler_->IntPtrConstant(0)),
165       &pass, FromId(label_id));
166   assembler_->Bind(&pass);
167 }
168 
169 
Build()170 MaybeHandle<Code> FastAccessorAssembler::Build() {
171   CHECK_EQ(kBuilding, state_);
172 
173   // Cleanup: We no longer need this.
174   nodes_.clear();
175   labels_.clear();
176 
177   // Export the schedule and call the compiler.
178   Schedule* schedule = assembler_->Export();
179   MaybeHandle<Code> code = Pipeline::GenerateCodeForCodeStub(
180       assembler_->isolate(), assembler_->call_descriptor(), assembler_->graph(),
181       schedule, Code::STUB, "FastAccessorAssembler");
182 
183   // Update state & return.
184   state_ = !code.is_null() ? kBuilt : kError;
185   return code;
186 }
187 
188 
FromRaw(Node * node)189 FastAccessorAssembler::ValueId FastAccessorAssembler::FromRaw(Node* node) {
190   nodes_.push_back(node);
191   ValueId value = {nodes_.size() - 1};
192   return value;
193 }
194 
195 
FromRaw(RawMachineLabel * label)196 FastAccessorAssembler::LabelId FastAccessorAssembler::FromRaw(
197     RawMachineLabel* label) {
198   labels_.push_back(label);
199   LabelId label_id = {labels_.size() - 1};
200   return label_id;
201 }
202 
203 
FromId(ValueId value) const204 Node* FastAccessorAssembler::FromId(ValueId value) const {
205   CHECK_LT(value.value_id, nodes_.size());
206   CHECK_NOT_NULL(nodes_.at(value.value_id));
207   return nodes_.at(value.value_id);
208 }
209 
210 
FromId(LabelId label) const211 RawMachineLabel* FastAccessorAssembler::FromId(LabelId label) const {
212   CHECK_LT(label.label_id, labels_.size());
213   CHECK_NOT_NULL(labels_.at(label.label_id));
214   return labels_.at(label.label_id);
215 }
216 
217 
218 }  // namespace compiler
219 }  // namespace internal
220 }  // namespace v8
221