Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 __ LoadObject(RAX, value->AsConstant()->instance()); | 45 __ LoadObject(RAX, value->AsConstant()->instance()); |
| 46 } | 46 } |
| 47 } else { | 47 } else { |
| 48 ASSERT(value->IsTemp()); | 48 ASSERT(value->IsTemp()); |
| 49 __ popq(RAX); | 49 __ popq(RAX); |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 | 53 |
| 54 void FlowGraphCompiler::VisitTemp(TempVal* val) { | 54 void FlowGraphCompiler::VisitTemp(TempVal* val) { |
| 55 Bailout("TempVal"); | 55 LoadValue(val); |
| 56 } | 56 } |
| 57 | 57 |
| 58 | 58 |
| 59 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { | 59 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { |
| 60 Bailout("ConstantVal"); | 60 LoadValue(val); |
| 61 } | 61 } |
| 62 | 62 |
| 63 | 63 |
| 64 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { | 64 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { |
| 65 Bailout("AssertAssignableComp"); | 65 Bailout("AssertAssignableComp"); |
| 66 } | 66 } |
| 67 | 67 |
| 68 | 68 |
| 69 // True iff. the arguments to a call will be properly pushed and can | |
| 70 // be popped after the call. | |
| 71 template <typename T> static bool VerifyCallComputation(T* comp) { | |
| 72 // Argument values should be consecutive temps. | |
| 73 // | |
| 74 // TODO(kmillikin): implement stack height tracking so we can also assert | |
| 75 // they are on top of the stack. | |
| 76 intptr_t previous = -1; | |
| 77 for (int i = 0; i < comp->ArgumentCount(); ++i) { | |
| 78 TempVal* temp = comp->ArgumentAt(i)->AsTemp(); | |
| 79 if (temp == NULL) return false; | |
| 80 if (i != 0) { | |
| 81 if (temp->index() != previous + 1) return false; | |
| 82 } | |
| 83 previous = temp->index(); | |
| 84 } | |
| 85 return true; | |
|
srdjan
2012/03/01 23:19:31
Can you check that last temp is on TOS, i.e., with
Kevin Millikin (Google)
2012/03/02 09:01:28
We can't easily check that it's actually on top of
| |
| 86 } | |
| 87 | |
| 88 | |
| 89 void FlowGraphCompiler::EmitInstanceCall(intptr_t node_id, | |
| 90 intptr_t token_index, | |
| 91 const String& function_name, | |
| 92 intptr_t argument_count, | |
| 93 const Array& argument_names, | |
| 94 intptr_t checked_argument_count) { | |
| 95 ICData& ic_data = | |
| 96 ICData::ZoneHandle(ICData::New(parsed_function_.function(), | |
| 97 function_name, | |
| 98 node_id, | |
| 99 checked_argument_count)); | |
| 100 const Array& arguments_descriptor = | |
| 101 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); | |
| 102 __ LoadObject(RBX, ic_data); | |
| 103 __ LoadObject(R10, arguments_descriptor); | |
| 104 | |
| 105 uword label_address = 0; | |
| 106 switch (checked_argument_count) { | |
| 107 case 1: | |
| 108 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); | |
| 109 break; | |
| 110 case 2: | |
| 111 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); | |
| 112 break; | |
| 113 default: | |
| 114 UNIMPLEMENTED(); | |
| 115 } | |
| 116 ExternalLabel target_label("InlineCache", label_address); | |
| 117 __ call(&target_label); | |
| 118 AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index); | |
| 119 __ addq(RSP, Immediate(argument_count * kWordSize)); | |
| 120 } | |
| 121 | |
| 122 | |
| 69 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { | 123 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { |
| 70 Bailout("InstanceCallComp"); | 124 ASSERT(VerifyCallComputation(comp)); |
| 125 EmitInstanceCall(comp->node_id(), | |
| 126 comp->token_index(), | |
| 127 comp->function_name(), | |
| 128 comp->ArgumentCount(), | |
| 129 comp->argument_names(), | |
| 130 comp->checked_argument_count()); | |
| 71 } | 131 } |
| 72 | 132 |
| 73 | 133 |
| 74 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { | 134 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { |
| 75 Bailout("StrictCompareComp"); | 135 Bailout("StrictCompareComp"); |
| 76 } | 136 } |
| 77 | 137 |
| 78 | 138 |
| 79 | 139 |
| 80 void FlowGraphCompiler::VisitStaticCall(StaticCallComp* comp) { | 140 void FlowGraphCompiler::VisitStaticCall(StaticCallComp* comp) { |
| 81 Bailout("StaticCallComp"); | 141 ASSERT(VerifyCallComputation(comp)); |
| 142 | |
| 143 int argument_count = comp->ArgumentCount(); | |
| 144 const Array& arguments_descriptor = | |
| 145 CodeGenerator::ArgumentsDescriptor(argument_count, | |
| 146 comp->argument_names()); | |
| 147 __ LoadObject(RBX, comp->function()); | |
| 148 __ LoadObject(R10, arguments_descriptor); | |
| 149 | |
| 150 GenerateCall(comp->token_index(), | |
| 151 &StubCode::CallStaticFunctionLabel(), | |
| 152 PcDescriptors::kFuncCall); | |
| 153 __ addq(RSP, Immediate(argument_count * kWordSize)); | |
| 82 } | 154 } |
| 83 | 155 |
| 84 | 156 |
| 85 void FlowGraphCompiler::VisitLoadLocal(LoadLocalComp* comp) { | 157 void FlowGraphCompiler::VisitLoadLocal(LoadLocalComp* comp) { |
| 86 if (comp->local().is_captured()) { | 158 if (comp->local().is_captured()) { |
| 87 Bailout("load of context variable"); | 159 Bailout("load of context variable"); |
| 88 } | 160 } |
| 89 __ movq(RAX, Address(RBP, comp->local().index() * kWordSize)); | 161 __ movq(RAX, Address(RBP, comp->local().index() * kWordSize)); |
| 90 } | 162 } |
| 91 | 163 |
| 92 | 164 |
| 93 void FlowGraphCompiler::VisitStoreLocal(StoreLocalComp* comp) { | 165 void FlowGraphCompiler::VisitStoreLocal(StoreLocalComp* comp) { |
| 94 if (comp->local().is_captured()) { | 166 if (comp->local().is_captured()) { |
| 95 Bailout("store to context variable"); | 167 Bailout("store to context variable"); |
| 96 } | 168 } |
| 97 LoadValue(comp->value()); | 169 LoadValue(comp->value()); |
| 98 __ movq(Address(RBP, comp->local().index() * kWordSize), RAX); | 170 __ movq(Address(RBP, comp->local().index() * kWordSize), RAX); |
| 99 } | 171 } |
| 100 | 172 |
| 101 | 173 |
| 174 void FlowGraphCompiler::VisitStoreIndexed(StoreIndexedComp* comp) { | |
| 175 // Call operator []= but preserve the third argument value under the | |
| 176 // arguments as the result of the computation. | |
| 177 const String& function_name = | |
| 178 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | |
| 179 // Placeholder is under value, index, and receiver. | |
| 180 const int kPlaceholderOffset = 3 * kWordSize; | |
| 181 __ movq(RAX, Address(RSP, 0)); // Value. | |
| 182 __ movq(Address(RSP, kPlaceholderOffset), RAX); | |
| 183 EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 3, | |
| 184 Array::ZoneHandle(), 1); | |
| 185 __ popq(RAX); | |
| 186 } | |
| 187 | |
| 188 | |
| 189 void FlowGraphCompiler::VisitInstanceSetter(InstanceSetterComp* comp) { | |
| 190 // Preserve the second argument under the arguments as the result of the | |
| 191 // computation, then call the getter. | |
|
srdjan
2012/03/01 23:19:31
Can you verify that place holder, value, array and
Kevin Millikin (Google)
2012/03/02 09:01:28
Yes.
| |
| 192 const String& function_name = | |
| 193 String::ZoneHandle(Field::SetterSymbol(comp->field_name())); | |
| 194 // Placeholder is under value and receiver. | |
| 195 const int kPlaceholderOffset = 2 * kWordSize; | |
| 196 __ movq(RAX, Address(RSP, 0)); // Value. | |
| 197 __ movq(Address(RSP, kPlaceholderOffset), RAX); | |
| 198 EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 2, | |
| 199 Array::ZoneHandle(), 1); | |
| 200 __ popq(RAX); | |
| 201 } | |
| 202 | |
| 203 | |
| 102 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { | 204 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { |
| 103 Bailout("JoinEntryInstr"); | 205 Bailout("JoinEntryInstr"); |
| 104 } | 206 } |
| 105 | 207 |
| 106 | 208 |
| 107 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { | 209 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { |
| 108 // Since we don't handle branching control flow yet, there is nothing to do. | 210 // Since we don't handle branching control flow yet, there is nothing to do. |
| 109 } | 211 } |
| 110 | 212 |
| 111 | 213 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, | 353 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, |
| 252 assembler_->CodeSize(), | 354 assembler_->CodeSize(), |
| 253 AstNode::kNoId, | 355 AstNode::kNoId, |
| 254 0, | 356 0, |
| 255 -1); | 357 -1); |
| 256 __ jmp(&StubCode::FixCallersTargetLabel()); | 358 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 257 } | 359 } |
| 258 | 360 |
| 259 | 361 |
| 260 // Infrastructure copied from class CodeGenerator. | 362 // Infrastructure copied from class CodeGenerator. |
| 363 void FlowGraphCompiler::GenerateCall(intptr_t token_index, | |
| 364 const ExternalLabel* label, | |
| 365 PcDescriptors::Kind kind) { | |
| 366 __ call(label); | |
| 367 AddCurrentDescriptor(kind, AstNode::kNoId, token_index); | |
| 368 } | |
| 369 | |
| 370 | |
| 261 void FlowGraphCompiler::GenerateCallRuntime(intptr_t node_id, | 371 void FlowGraphCompiler::GenerateCallRuntime(intptr_t node_id, |
| 262 intptr_t token_index, | 372 intptr_t token_index, |
| 263 const RuntimeEntry& entry) { | 373 const RuntimeEntry& entry) { |
| 264 __ CallRuntimeFromDart(entry); | 374 __ CallRuntimeFromDart(entry); |
| 265 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); | 375 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); |
| 266 } | 376 } |
| 267 | 377 |
| 268 | 378 |
| 269 // Uses current pc position and try-index. | 379 // Uses current pc position and try-index. |
| 270 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, | 380 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 297 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 407 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 298 // We don't compile exception handlers yet. | 408 // We don't compile exception handlers yet. |
| 299 code.set_exception_handlers( | 409 code.set_exception_handlers( |
| 300 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 410 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); |
| 301 } | 411 } |
| 302 | 412 |
| 303 | 413 |
| 304 } // namespace dart | 414 } // namespace dart |
| 305 | 415 |
| 306 #endif // defined TARGET_ARCH_X64 | 416 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |