| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1215 __ popl(EAX); // Pop argument (type arguments of object). | 1215 __ popl(EAX); // Pop argument (type arguments of object). |
| 1216 __ popl(EAX); // Pop argument (class of object). | 1216 __ popl(EAX); // Pop argument (class of object). |
| 1217 __ popl(EAX); // Pop result (newly allocated object). | 1217 __ popl(EAX); // Pop result (newly allocated object). |
| 1218 // EAX: new object | 1218 // EAX: new object |
| 1219 // Restore the frame pointer. | 1219 // Restore the frame pointer. |
| 1220 __ LeaveFrame(); | 1220 __ LeaveFrame(); |
| 1221 __ ret(); | 1221 __ ret(); |
| 1222 } | 1222 } |
| 1223 | 1223 |
| 1224 | 1224 |
| 1225 // TODO(regis): This stub is not called anymore to allocate regular closures, | |
| 1226 // but only implicit instance closures. Simplify. | |
| 1227 | |
| 1228 // Called for inline allocation of closures. | |
| 1229 // Input parameters: | |
| 1230 // ESP + 8 : receiver (null if not an implicit instance closure). | |
| 1231 // ESP + 4 : type arguments object (null if class is no parameterized). | |
| 1232 // ESP : points to return address. | |
| 1233 // Uses EAX, EBX, ECX, EDX as temporary registers. | |
| 1234 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | |
| 1235 const Function& func) { | |
| 1236 const Immediate& raw_null = | |
| 1237 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 1238 ASSERT(func.IsClosureFunction()); | |
| 1239 ASSERT(!func.IsImplicitStaticClosureFunction()); | |
| 1240 const bool is_implicit_instance_closure = | |
| 1241 func.IsImplicitInstanceClosureFunction(); | |
| 1242 const Class& cls = Class::ZoneHandle(func.signature_class()); | |
| 1243 const bool has_type_arguments = cls.NumTypeArguments() > 0; | |
| 1244 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | |
| 1245 const intptr_t kReceiverOffset = 2 * kWordSize; | |
| 1246 const intptr_t closure_size = Closure::InstanceSize(); | |
| 1247 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. | |
| 1248 if (FLAG_inline_alloc && | |
| 1249 Heap::IsAllocatableInNewSpace(closure_size + context_size)) { | |
| 1250 Label slow_case; | |
| 1251 Heap* heap = Isolate::Current()->heap(); | |
| 1252 __ movl(EAX, Address::Absolute(heap->TopAddress())); | |
| 1253 __ leal(EBX, Address(EAX, closure_size)); | |
| 1254 if (is_implicit_instance_closure) { | |
| 1255 __ movl(ECX, EBX); // ECX: new context address. | |
| 1256 __ addl(EBX, Immediate(context_size)); | |
| 1257 } | |
| 1258 // Check if the allocation fits into the remaining space. | |
| 1259 // EAX: potential new closure object. | |
| 1260 // ECX: potential new context object (only if is_implicit_closure). | |
| 1261 // EBX: potential next object start. | |
| 1262 __ cmpl(EBX, Address::Absolute(heap->EndAddress())); | |
| 1263 if (FLAG_use_slow_path) { | |
| 1264 __ jmp(&slow_case); | |
| 1265 } else { | |
| 1266 __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump); | |
| 1267 } | |
| 1268 | |
| 1269 // Successfully allocated the object, now update top to point to | |
| 1270 // next object start and initialize the object. | |
| 1271 __ movl(Address::Absolute(heap->TopAddress()), EBX); | |
| 1272 // EAX: new closure object. | |
| 1273 // ECX: new context object (only if is_implicit_closure). | |
| 1274 if (is_implicit_instance_closure) { | |
| 1275 // This closure allocates a context, update allocation stats. | |
| 1276 // EBX: context size. | |
| 1277 __ movl(EBX, Immediate(context_size)); | |
| 1278 // EDX: Clobbered. | |
| 1279 __ UpdateAllocationStatsWithSize(kContextCid, EBX, EDX); | |
| 1280 } | |
| 1281 // The closure allocation is attributed to the signature class. | |
| 1282 // EDX: Will be clobbered. | |
| 1283 __ UpdateAllocationStats(cls.id(), EDX); | |
| 1284 | |
| 1285 // EAX: new closure object. | |
| 1286 // ECX: new context object (only if is_implicit_closure). | |
| 1287 // Set the tags. | |
| 1288 uword tags = 0; | |
| 1289 tags = RawObject::SizeTag::update(closure_size, tags); | |
| 1290 tags = RawObject::ClassIdTag::update(cls.id(), tags); | |
| 1291 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); | |
| 1292 | |
| 1293 // Initialize the function field in the object. | |
| 1294 // EAX: new closure object. | |
| 1295 // ECX: new context object (only if is_implicit_closure). | |
| 1296 __ LoadObject(EDX, func); // Load function of closure to be allocated. | |
| 1297 __ movl(Address(EAX, Closure::function_offset()), EDX); | |
| 1298 | |
| 1299 // Setup the context for this closure. | |
| 1300 if (is_implicit_instance_closure) { | |
| 1301 // Initialize the new context capturing the receiver. | |
| 1302 const Class& context_class = Class::ZoneHandle(Object::context_class()); | |
| 1303 // Set the tags. | |
| 1304 uword tags = 0; | |
| 1305 tags = RawObject::SizeTag::update(context_size, tags); | |
| 1306 tags = RawObject::ClassIdTag::update(context_class.id(), tags); | |
| 1307 __ movl(Address(ECX, Context::tags_offset()), Immediate(tags)); | |
| 1308 | |
| 1309 // Set number of variables field to 1 (for captured receiver). | |
| 1310 __ movl(Address(ECX, Context::num_variables_offset()), Immediate(1)); | |
| 1311 | |
| 1312 // Set isolate field to isolate of current context. | |
| 1313 __ movl(EDX, FieldAddress(CTX, Context::isolate_offset())); | |
| 1314 __ movl(Address(ECX, Context::isolate_offset()), EDX); | |
| 1315 | |
| 1316 // Set the parent to null. | |
| 1317 __ movl(Address(ECX, Context::parent_offset()), raw_null); | |
| 1318 | |
| 1319 // Initialize the context variable to the receiver. | |
| 1320 __ movl(EDX, Address(ESP, kReceiverOffset)); | |
| 1321 __ movl(Address(ECX, Context::variable_offset(0)), EDX); | |
| 1322 | |
| 1323 // Set the newly allocated context in the newly allocated closure. | |
| 1324 __ addl(ECX, Immediate(kHeapObjectTag)); | |
| 1325 __ movl(Address(EAX, Closure::context_offset()), ECX); | |
| 1326 } else { | |
| 1327 __ movl(Address(EAX, Closure::context_offset()), CTX); | |
| 1328 } | |
| 1329 | |
| 1330 // Set the type arguments field in the newly allocated closure. | |
| 1331 __ movl(EDX, Address(ESP, kTypeArgumentsOffset)); | |
| 1332 __ movl(Address(EAX, Closure::type_arguments_offset()), EDX); | |
| 1333 | |
| 1334 // Done allocating and initializing the instance. | |
| 1335 // EAX: new object. | |
| 1336 __ addl(EAX, Immediate(kHeapObjectTag)); | |
| 1337 __ ret(); | |
| 1338 | |
| 1339 __ Bind(&slow_case); | |
| 1340 } | |
| 1341 if (has_type_arguments) { | |
| 1342 __ movl(ECX, Address(ESP, kTypeArgumentsOffset)); | |
| 1343 } | |
| 1344 if (is_implicit_instance_closure) { | |
| 1345 __ movl(EAX, Address(ESP, kReceiverOffset)); | |
| 1346 } | |
| 1347 // Create a stub frame as we are pushing some objects on the stack before | |
| 1348 // calling into the runtime. | |
| 1349 __ EnterStubFrame(); | |
| 1350 __ pushl(raw_null); // Setup space on stack for return value. | |
| 1351 __ PushObject(func); | |
| 1352 if (is_implicit_instance_closure) { | |
| 1353 __ pushl(EAX); // Receiver. | |
| 1354 } | |
| 1355 if (has_type_arguments) { | |
| 1356 __ pushl(ECX); // Push type arguments of closure to be allocated. | |
| 1357 } else { | |
| 1358 __ pushl(raw_null); // Push null type arguments. | |
| 1359 } | |
| 1360 if (is_implicit_instance_closure) { | |
| 1361 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry, 3); | |
| 1362 __ popl(EAX); // Pop argument (type arguments of object). | |
| 1363 __ popl(EAX); // Pop receiver. | |
| 1364 } else { | |
| 1365 ASSERT(func.IsNonImplicitClosureFunction()); | |
| 1366 __ CallRuntime(kAllocateClosureRuntimeEntry, 2); | |
| 1367 __ popl(EAX); // Pop argument (type arguments of object). | |
| 1368 } | |
| 1369 __ popl(EAX); // Pop function object. | |
| 1370 __ popl(EAX); | |
| 1371 // EAX: new object | |
| 1372 // Restore the frame pointer. | |
| 1373 __ LeaveFrame(); | |
| 1374 __ ret(); | |
| 1375 } | |
| 1376 | |
| 1377 | |
| 1378 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1225 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
| 1379 // from the entry code of a dart function after an error in passed argument | 1226 // from the entry code of a dart function after an error in passed argument |
| 1380 // name or number is detected. | 1227 // name or number is detected. |
| 1381 // Input parameters: | 1228 // Input parameters: |
| 1382 // ESP : points to return address. | 1229 // ESP : points to return address. |
| 1383 // ESP + 4 : address of last argument. | 1230 // ESP + 4 : address of last argument. |
| 1384 // ECX : ic-data. | 1231 // ECX : ic-data. |
| 1385 // EDX : arguments descriptor array. | 1232 // EDX : arguments descriptor array. |
| 1386 // Uses EAX, EBX, EDI as temporary registers. | 1233 // Uses EAX, EBX, EDI as temporary registers. |
| 1387 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1234 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2119 const Register temp = ECX; | 1966 const Register temp = ECX; |
| 2120 __ movl(left, Address(ESP, 2 * kWordSize)); | 1967 __ movl(left, Address(ESP, 2 * kWordSize)); |
| 2121 __ movl(right, Address(ESP, 1 * kWordSize)); | 1968 __ movl(right, Address(ESP, 1 * kWordSize)); |
| 2122 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1969 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2123 __ ret(); | 1970 __ ret(); |
| 2124 } | 1971 } |
| 2125 | 1972 |
| 2126 } // namespace dart | 1973 } // namespace dart |
| 2127 | 1974 |
| 2128 #endif // defined TARGET_ARCH_IA32 | 1975 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |