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 |