OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/fast-accessor-assembler.h" | 5 #include "src/fast-accessor-assembler.h" |
6 | 6 |
7 #include "src/base/logging.h" | 7 #include "src/base/logging.h" |
8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
9 #include "src/code-stubs.h" // For CallApiCallbackStub. | 9 #include "src/code-stubs.h" // For CallApiCallbackStub. |
10 #include "src/handles-inl.h" | 10 #include "src/handles-inl.h" |
(...skipping 25 matching lines...) Expand all Loading... | |
36 CHECK_EQ(kBuilding, state_); | 36 CHECK_EQ(kBuilding, state_); |
37 | 37 |
38 // For JS functions, the receiver is parameter 0. | 38 // For JS functions, the receiver is parameter 0. |
39 return FromRaw(assembler_->Parameter(0)); | 39 return FromRaw(assembler_->Parameter(0)); |
40 } | 40 } |
41 | 41 |
42 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadInternalField( | 42 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadInternalField( |
43 ValueId value, int field_no) { | 43 ValueId value, int field_no) { |
44 CHECK_EQ(kBuilding, state_); | 44 CHECK_EQ(kBuilding, state_); |
45 | 45 |
46 // Determine the 'value' object's instance type. | |
47 Node* object_map = assembler_->LoadObjectField( | |
48 FromId(value), Internals::kHeapObjectMapOffset, MachineType::Pointer()); | |
49 Node* instance_type = assembler_->WordAnd( | |
50 assembler_->LoadObjectField(object_map, | |
51 Internals::kMapInstanceTypeAndBitFieldOffset, | |
52 MachineType::Uint16()), | |
53 assembler_->IntPtrConstant(0xff)); | |
54 | |
55 // Check whether we have a proper JSObject. | |
56 CodeStubAssembler::Variable result(assembler_.get(), | 46 CodeStubAssembler::Variable result(assembler_.get(), |
57 MachineRepresentation::kTagged); | 47 MachineRepresentation::kTagged); |
58 CodeStubAssembler::Label is_jsobject(assembler_.get()); | 48 LabelId is_not_jsobject = MakeLabel(); |
59 CodeStubAssembler::Label maybe_api_object(assembler_.get()); | |
60 CodeStubAssembler::Label is_not_jsobject(assembler_.get()); | |
61 CodeStubAssembler::Label merge(assembler_.get(), &result); | 49 CodeStubAssembler::Label merge(assembler_.get(), &result); |
62 assembler_->Branch( | |
63 assembler_->WordEqual( | |
64 instance_type, assembler_->IntPtrConstant(Internals::kJSObjectType)), | |
65 &is_jsobject, &maybe_api_object); | |
66 | 50 |
67 // JSObject? Then load the internal field field_no. | 51 CheckIsJSObjectOrJump(value, is_not_jsobject); |
68 assembler_->Bind(&is_jsobject); | 52 |
69 Node* internal_field = assembler_->LoadObjectField( | 53 Node* internal_field = assembler_->LoadObjectField( |
70 FromId(value), JSObject::kHeaderSize + kPointerSize * field_no, | 54 FromId(value), JSObject::kHeaderSize + kPointerSize * field_no, |
71 MachineType::Pointer()); | 55 MachineType::Pointer()); |
56 | |
72 result.Bind(internal_field); | 57 result.Bind(internal_field); |
73 assembler_->Goto(&merge); | 58 assembler_->Goto(&merge); |
74 | 59 |
75 assembler_->Bind(&maybe_api_object); | 60 // Return null, mimicking the C++ counterpart. |
76 assembler_->Branch( | 61 SetLabel(is_not_jsobject); |
77 assembler_->WordEqual(instance_type, assembler_->IntPtrConstant( | 62 result.Bind(assembler_->NullConstant()); |
78 Internals::kJSApiObjectType)), | |
79 &is_jsobject, &is_not_jsobject); | |
80 | |
81 // No JSObject? Return undefined. | |
82 // TODO(vogelheim): Check whether this is the appropriate action, or whether | |
83 // the method should take a label instead. | |
84 assembler_->Bind(&is_not_jsobject); | |
85 Node* fail_value = assembler_->UndefinedConstant(); | |
86 result.Bind(fail_value); | |
87 assembler_->Goto(&merge); | 63 assembler_->Goto(&merge); |
88 | 64 |
89 // Return. | 65 // Return. |
90 assembler_->Bind(&merge); | 66 assembler_->Bind(&merge); |
91 return FromRaw(result.value()); | 67 return FromRaw(result.value()); |
92 } | 68 } |
93 | 69 |
70 FastAccessorAssembler::ValueId | |
71 FastAccessorAssembler::LoadInternalFieldUnchecked(ValueId value, int field_no) { | |
72 CHECK_EQ(kBuilding, state_); | |
73 | |
74 // Defensive debug checks. | |
75 if (FLAG_debug_code) { | |
76 LabelId is_jsobject = MakeLabel(); | |
77 LabelId is_not_jsobject = MakeLabel(); | |
78 CheckIsJSObjectOrJump(value, is_not_jsobject); | |
79 assembler_->Goto(FromId(is_jsobject)); | |
80 | |
81 SetLabel(is_not_jsobject); | |
82 // Deliberately crash. | |
vogelheim
2016/08/08 11:47:22
Hmm. Actually, we force a debug break (which termi
Alfonso
2016/08/08 13:03:28
Acknowledged.
| |
83 assembler_->DebugBreak(); | |
84 assembler_->Goto(FromId(is_jsobject)); | |
85 | |
86 SetLabel(is_jsobject); | |
87 } | |
88 | |
89 Node* result = assembler_->LoadObjectField( | |
90 FromId(value), JSObject::kHeaderSize + kPointerSize * field_no, | |
91 MachineType::Pointer()); | |
92 | |
93 return FromRaw(result); | |
94 } | |
95 | |
94 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadValue(ValueId value, | 96 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadValue(ValueId value, |
95 int offset) { | 97 int offset) { |
96 CHECK_EQ(kBuilding, state_); | 98 CHECK_EQ(kBuilding, state_); |
97 return FromRaw(assembler_->LoadBufferObject(FromId(value), offset, | 99 return FromRaw(assembler_->LoadBufferObject(FromId(value), offset, |
98 MachineType::IntPtr())); | 100 MachineType::IntPtr())); |
99 } | 101 } |
100 | 102 |
101 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadObject(ValueId value, | 103 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadObject(ValueId value, |
102 int offset) { | 104 int offset) { |
103 CHECK_EQ(kBuilding, state_); | 105 CHECK_EQ(kBuilding, state_); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 assembler_->Branch( | 157 assembler_->Branch( |
156 assembler_->WordEqual(FromId(value_id), assembler_->IntPtrConstant(0)), | 158 assembler_->WordEqual(FromId(value_id), assembler_->IntPtrConstant(0)), |
157 FromId(label_id), &pass); | 159 FromId(label_id), &pass); |
158 assembler_->Bind(&pass); | 160 assembler_->Bind(&pass); |
159 } | 161 } |
160 | 162 |
161 FastAccessorAssembler::ValueId FastAccessorAssembler::Call( | 163 FastAccessorAssembler::ValueId FastAccessorAssembler::Call( |
162 FunctionCallback callback_function, ValueId arg) { | 164 FunctionCallback callback_function, ValueId arg) { |
163 CHECK_EQ(kBuilding, state_); | 165 CHECK_EQ(kBuilding, state_); |
164 | 166 |
167 CodeStubAssembler::Label deferred(assembler_.get(), | |
vogelheim
2016/08/08 11:47:22
This is a good change, but unrelated to what the C
Alfonso
2016/08/08 13:03:28
Reverting this, even if is the logical thing to do
| |
168 compiler::CodeAssembler::Label::kDeferred); | |
169 assembler_->Goto(&deferred); | |
170 assembler_->Bind(&deferred); | |
171 | |
165 // Wrap the FunctionCallback in an ExternalReference. | 172 // Wrap the FunctionCallback in an ExternalReference. |
166 ApiFunction callback_api_function(FUNCTION_ADDR(callback_function)); | 173 ApiFunction callback_api_function(FUNCTION_ADDR(callback_function)); |
167 ExternalReference callback(&callback_api_function, | 174 ExternalReference callback(&callback_api_function, |
168 ExternalReference::DIRECT_API_CALL, isolate()); | 175 ExternalReference::DIRECT_API_CALL, isolate()); |
169 | 176 |
170 // Create & call API callback via stub. | 177 // Create & call API callback via stub. |
171 CallApiCallbackStub stub(isolate(), 1, true, true); | 178 CallApiCallbackStub stub(isolate(), 1, true, true); |
172 DCHECK_EQ(5, stub.GetCallInterfaceDescriptor().GetParameterCount()); | 179 DCHECK_EQ(5, stub.GetCallInterfaceDescriptor().GetParameterCount()); |
173 DCHECK_EQ(1, stub.GetCallInterfaceDescriptor().GetStackParameterCount()); | 180 DCHECK_EQ(1, stub.GetCallInterfaceDescriptor().GetStackParameterCount()); |
174 // TODO(vogelheim): There is currently no clean way to retrieve the context | 181 // TODO(vogelheim): There is currently no clean way to retrieve the context |
(...skipping 11 matching lines...) Expand all Loading... | |
186 assembler_->UndefinedConstant(), /* call_data (undefined) */ | 193 assembler_->UndefinedConstant(), /* call_data (undefined) */ |
187 assembler_->Parameter(0), /* receiver (same as holder in this case) */ | 194 assembler_->Parameter(0), /* receiver (same as holder in this case) */ |
188 assembler_->ExternalConstant(callback), /* API callback function */ | 195 assembler_->ExternalConstant(callback), /* API callback function */ |
189 | 196 |
190 // JS arguments, on stack: | 197 // JS arguments, on stack: |
191 FromId(arg)); | 198 FromId(arg)); |
192 | 199 |
193 return FromRaw(call); | 200 return FromRaw(call); |
194 } | 201 } |
195 | 202 |
203 void FastAccessorAssembler::CheckIsJSObjectOrJump(ValueId value_id, | |
204 LabelId label_id) { | |
205 CHECK_EQ(kBuilding, state_); | |
206 | |
207 // Determine the 'value' object's instance type. | |
208 Node* object_map = assembler_->LoadObjectField( | |
209 FromId(value_id), Internals::kHeapObjectMapOffset, | |
210 MachineType::Pointer()); | |
211 | |
212 Node* instance_type = assembler_->WordAnd( | |
213 assembler_->LoadObjectField(object_map, | |
214 Internals::kMapInstanceTypeAndBitFieldOffset, | |
215 MachineType::Uint16()), | |
216 assembler_->IntPtrConstant(0xff)); | |
217 | |
218 CodeStubAssembler::Label is_jsobject(assembler_.get()); | |
219 | |
220 // Check whether we have a proper JSObject. | |
221 assembler_->GotoIf( | |
222 assembler_->WordEqual( | |
223 instance_type, assembler_->IntPtrConstant(Internals::kJSObjectType)), | |
224 &is_jsobject); | |
225 | |
226 // JSApiObject?. | |
227 assembler_->GotoUnless( | |
228 assembler_->WordEqual(instance_type, assembler_->IntPtrConstant( | |
229 Internals::kJSApiObjectType)), | |
230 FromId(label_id)); | |
231 | |
232 // Continue. | |
233 assembler_->Goto(&is_jsobject); | |
234 assembler_->Bind(&is_jsobject); | |
235 } | |
236 | |
196 MaybeHandle<Code> FastAccessorAssembler::Build() { | 237 MaybeHandle<Code> FastAccessorAssembler::Build() { |
197 CHECK_EQ(kBuilding, state_); | 238 CHECK_EQ(kBuilding, state_); |
198 Handle<Code> code = assembler_->GenerateCode(); | 239 Handle<Code> code = assembler_->GenerateCode(); |
199 state_ = !code.is_null() ? kBuilt : kError; | 240 state_ = !code.is_null() ? kBuilt : kError; |
200 Clear(); | 241 Clear(); |
201 return code; | 242 return code; |
202 } | 243 } |
203 | 244 |
204 FastAccessorAssembler::ValueId FastAccessorAssembler::FromRaw(Node* node) { | 245 FastAccessorAssembler::ValueId FastAccessorAssembler::FromRaw(Node* node) { |
205 nodes_.push_back(node); | 246 nodes_.push_back(node); |
(...skipping 23 matching lines...) Expand all Loading... | |
229 void FastAccessorAssembler::Clear() { | 270 void FastAccessorAssembler::Clear() { |
230 for (auto label : labels_) { | 271 for (auto label : labels_) { |
231 delete label; | 272 delete label; |
232 } | 273 } |
233 nodes_.clear(); | 274 nodes_.clear(); |
234 labels_.clear(); | 275 labels_.clear(); |
235 } | 276 } |
236 | 277 |
237 } // namespace internal | 278 } // namespace internal |
238 } // namespace v8 | 279 } // namespace v8 |
OLD | NEW |