Chromium Code Reviews| 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 |