Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(302)

Side by Side Diff: runtime/vm/code_generator_ia32.cc

Issue 10368004: Properly set the element type of literal lists. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 } 927 }
928 928
929 929
930 void CodeGenerator::VisitArrayNode(ArrayNode* node) { 930 void CodeGenerator::VisitArrayNode(ArrayNode* node) {
931 // Evaluate the array elements. 931 // Evaluate the array elements.
932 for (int i = 0; i < node->length(); i++) { 932 for (int i = 0; i < node->length(); i++) {
933 AstNode* element = node->ElementAt(i); 933 AstNode* element = node->ElementAt(i);
934 element->Visit(this); 934 element->Visit(this);
935 } 935 }
936 936
937 const AbstractTypeArguments& element_type = node->type_arguments();
938 const bool instantiate_type_arguments = true;
939 GenerateTypeArguments(node->id(),
940 node->token_index(),
941 element_type,
942 instantiate_type_arguments);
943 __ popl(ECX);
944 __ movl(EDX, Immediate(Smi::RawValue(node->length())));
945
937 // Allocate the array. 946 // Allocate the array.
938 // EDX : Array length as Smi. 947 // EDX : Array length as Smi.
939 // ECX : element type for the array. 948 // ECX : element type for the array.
940 __ movl(EDX, Immediate(Smi::RawValue(node->length())));
941 const AbstractTypeArguments& element_type = node->type_arguments();
942 ASSERT(element_type.IsNull() || element_type.IsInstantiated());
943 __ LoadObject(ECX, element_type);
944 GenerateCall(node->token_index(), 949 GenerateCall(node->token_index(),
945 &StubCode::AllocateArrayLabel(), 950 &StubCode::AllocateArrayLabel(),
946 PcDescriptors::kOther); 951 PcDescriptors::kOther);
947 952
948 // Pop the element values from the stack into the array. 953 // Pop the element values from the stack into the array.
949 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); 954 __ leal(ECX, FieldAddress(EAX, Array::data_offset()));
950 for (int i = node->length() - 1; i >= 0; i--) { 955 for (int i = node->length() - 1; i >= 0; i--) {
951 __ popl(Address(ECX, i * kWordSize)); 956 __ popl(Address(ECX, i * kWordSize));
952 } 957 }
953 958
(...skipping 1434 matching lines...) Expand 10 before | Expand all | Expand 10 after
2388 intptr_t type_arguments_instance_field_offset = 2393 intptr_t type_arguments_instance_field_offset =
2389 instantiator_class.type_arguments_instance_field_offset(); 2394 instantiator_class.type_arguments_instance_field_offset();
2390 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); 2395 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments);
2391 __ movl(EBX, FieldAddress(EBX, type_arguments_instance_field_offset)); 2396 __ movl(EBX, FieldAddress(EBX, type_arguments_instance_field_offset));
2392 __ pushl(EBX); 2397 __ pushl(EBX);
2393 } 2398 }
2394 } 2399 }
2395 } 2400 }
2396 2401
2397 2402
2398 // Pushes the type arguments on the stack in preparation of a constructor or 2403 // Pushes the type arguments on the stack in preparation of an allocation call.
2399 // factory call. 2404 // If instantiate_type_arguments is true, the instantiated type arguments
2400 // For a factory call, instantiates (possibly requiring an additional run time 2405 // are pushed on the stack (after an instantiation run time call, if necessary).
2401 // call) and pushes the type argument vector that will be passed as implicit 2406 // If instantiate_type_arguments is false, the (possibly uninstantiated) type
2402 // first parameter to the factory. 2407 // arguments are pushed on the stack, as well as the type arguments of the
2403 // For a constructor call allocating an object of a parameterized class, pushes 2408 // instantiator (or the special kNoInstantiator Smi marker, if the type
2404 // the type arguments and the type arguments of the instantiator, without ever 2409 // arguments are instantiated).
2405 // generating an additional run time call. 2410 void CodeGenerator::GenerateTypeArguments(
2406 // Does nothing for a constructor call allocating an object of a non 2411 intptr_t node_id,
2407 // parameterized class. 2412 intptr_t token_index,
2408 // Note that a class without proper type parameters may still be parameterized, 2413 const AbstractTypeArguments& type_arguments,
2409 // e.g. class A extends Array<int>. 2414 bool instantiate_type_arguments) {
2410 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node,
2411 bool requires_type_arguments) {
2412 const Immediate raw_null = 2415 const Immediate raw_null =
2413 Immediate(reinterpret_cast<intptr_t>(Object::null())); 2416 Immediate(reinterpret_cast<intptr_t>(Object::null()));
2414 // Instantiate the type arguments if necessary. 2417 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) {
2415 if (node->type_arguments().IsNull() || 2418 // The type arguments are instantiated.
2416 node->type_arguments().IsInstantiated()) { 2419 __ PushObject(type_arguments);
2417 if (requires_type_arguments) { 2420 if (!instantiate_type_arguments) {
2418 // A factory requires the type arguments as first parameter. 2421 // The type arguments of the instantiator are not needed, since the
2419 __ PushObject(node->type_arguments()); 2422 // type arguments are instantiated.
2420 if (!node->constructor().IsFactory()) { 2423 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
2421 // The non-factory allocator additionally requires the instantiator
2422 // type arguments which are not needed here, since the type arguments
2423 // are instantiated.
2424 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
2425 }
2426 } 2424 }
2427 } else { 2425 } else {
2428 // The type arguments are uninstantiated. 2426 // The type arguments are uninstantiated.
2429 ASSERT(requires_type_arguments); 2427 GenerateInstantiatorTypeArguments(token_index);
2430 GenerateInstantiatorTypeArguments(node->token_index());
2431 __ popl(EAX); // Pop instantiator. 2428 __ popl(EAX); // Pop instantiator.
2432 // EAX is the instantiator AbstractTypeArguments object (or null). 2429 // EAX is the instantiator AbstractTypeArguments object (or null).
2433 // If the instantiator is null and if the type argument vector 2430 // If the instantiator is null and if the type argument vector
2434 // instantiated from null becomes a vector of Dynamic, then use null as 2431 // instantiated from null becomes a vector of Dynamic, then use null as
2435 // the type arguments. 2432 // the type arguments.
2436 Label type_arguments_instantiated; 2433 Label type_arguments_instantiated;
2437 const intptr_t len = node->type_arguments().Length(); 2434 const intptr_t len = type_arguments.Length();
2438 if (node->type_arguments().IsRawInstantiatedRaw(len)) { 2435 if (type_arguments.IsRawInstantiatedRaw(len)) {
2439 __ cmpl(EAX, raw_null); 2436 __ cmpl(EAX, raw_null);
2440 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2437 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2441 } 2438 }
2442 // Instantiate non-null type arguments. 2439 // Instantiate non-null type arguments.
2443 if (node->type_arguments().IsUninstantiatedIdentity()) { 2440 if (type_arguments.IsUninstantiatedIdentity()) {
2444 // Check if the instantiator type argument vector is a TypeArguments of a 2441 // Check if the instantiator type argument vector is a TypeArguments of a
2445 // matching length and, if so, use it as the instantiated type_arguments. 2442 // matching length and, if so, use it as the instantiated type_arguments.
2446 // No need to check RAX for null (again), because a null instance will 2443 // No need to check RAX for null (again), because a null instance will
2447 // have the wrong class (Null instead of TypeArguments). 2444 // have the wrong class (Null instead of TypeArguments).
2448 Label type_arguments_uninstantiated; 2445 Label type_arguments_uninstantiated;
2449 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); 2446 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class()));
2450 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); 2447 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset()));
2451 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); 2448 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
2452 Immediate arguments_length =
2453 Immediate(Smi::RawValue(node->type_arguments().Length()));
2454 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), 2449 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()),
2455 arguments_length); 2450 Immediate(Smi::RawValue(len)));
2456 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2451 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2457 __ Bind(&type_arguments_uninstantiated); 2452 __ Bind(&type_arguments_uninstantiated);
2458 } 2453 }
2459 if (node->constructor().IsFactory()) { 2454 if (instantiate_type_arguments) {
2460 // A runtime call to instantiate the type arguments is required before 2455 // A runtime call to instantiate the type arguments is required.
2461 // calling the factory.
2462 __ PushObject(Object::ZoneHandle()); // Make room for the result. 2456 __ PushObject(Object::ZoneHandle()); // Make room for the result.
2463 __ PushObject(node->type_arguments()); 2457 __ PushObject(type_arguments);
2464 __ pushl(EAX); // Push instantiator type arguments. 2458 __ pushl(EAX); // Push instantiator type arguments.
2465 GenerateCallRuntime(node->id(), 2459 GenerateCallRuntime(node_id,
2466 node->token_index(), 2460 token_index,
2467 kInstantiateTypeArgumentsRuntimeEntry); 2461 kInstantiateTypeArgumentsRuntimeEntry);
2468 __ popl(EAX); // Pop instantiator type arguments. 2462 __ popl(EAX); // Pop instantiator type arguments.
2469 __ popl(EAX); // Pop uninstantiated type arguments. 2463 __ popl(EAX); // Pop uninstantiated type arguments.
2470 __ popl(EAX); // Pop instantiated type arguments. 2464 __ popl(EAX); // Pop instantiated type arguments.
2471 __ Bind(&type_arguments_instantiated); 2465 __ Bind(&type_arguments_instantiated);
2472 __ pushl(EAX); // Instantiated type arguments. 2466 __ pushl(EAX); // Instantiated type arguments.
2473 } else { 2467 } else {
2474 // In the non-factory case, we rely on the allocation stub to 2468 // The allocation stub will instantiate the type arguments.
2475 // instantiate the type arguments. 2469 __ PushObject(type_arguments);
2476 __ PushObject(node->type_arguments());
2477 __ pushl(EAX); // Instantiator type arguments. 2470 __ pushl(EAX); // Instantiator type arguments.
2478 Label type_arguments_pushed; 2471 Label type_arguments_pushed;
2479 __ jmp(&type_arguments_pushed, Assembler::kNearJump); 2472 __ jmp(&type_arguments_pushed, Assembler::kNearJump);
2480 2473
2481 __ Bind(&type_arguments_instantiated); 2474 __ Bind(&type_arguments_instantiated);
2482 __ pushl(EAX); // Instantiated type arguments. 2475 __ pushl(EAX); // Instantiated type arguments.
2483 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); 2476 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
2484 __ Bind(&type_arguments_pushed); 2477 __ Bind(&type_arguments_pushed);
2485 } 2478 }
2486 } 2479 }
2487 } 2480 }
2488 2481
2489 2482
2490 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { 2483 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) {
2491 if (node->constructor().IsFactory()) { 2484 if (node->constructor().IsFactory()) {
2492 const bool requires_type_arguments = true; // Always first arg to factory. 2485 const bool instantiate_type_arguments = true; // First argument to factory.
2493 GenerateTypeArguments(node, requires_type_arguments); 2486 GenerateTypeArguments(node->id(),
2487 node->token_index(),
2488 node->type_arguments(),
2489 instantiate_type_arguments);
2494 // The top of stack is an instantiated AbstractTypeArguments object 2490 // The top of stack is an instantiated AbstractTypeArguments object
2495 // (or null). 2491 // (or null).
2496 int num_args = node->arguments()->length() + 1; // +1 to include type args. 2492 int num_args = node->arguments()->length() + 1; // +1 to include type args.
2497 node->arguments()->Visit(this); 2493 node->arguments()->Visit(this);
2498 // Call the factory. 2494 // Call the factory.
2499 __ LoadObject(ECX, node->constructor()); 2495 __ LoadObject(ECX, node->constructor());
2500 __ LoadObject(EDX, ArgumentsDescriptor(num_args, 2496 __ LoadObject(EDX, ArgumentsDescriptor(num_args,
2501 node->arguments()->names())); 2497 node->arguments()->names()));
2502 GenerateCall(node->token_index(), 2498 GenerateCall(node->token_index(),
2503 &StubCode::CallStaticFunctionLabel(), 2499 &StubCode::CallStaticFunctionLabel(),
2504 PcDescriptors::kFuncCall); 2500 PcDescriptors::kFuncCall);
2505 // Factory constructor returns object in EAX. 2501 // Factory constructor returns object in EAX.
2506 __ addl(ESP, Immediate(num_args * kWordSize)); 2502 __ addl(ESP, Immediate(num_args * kWordSize));
2507 if (IsResultNeeded(node)) { 2503 if (IsResultNeeded(node)) {
2508 __ pushl(EAX); 2504 __ pushl(EAX);
2509 } 2505 }
2510 return; 2506 return;
2511 } 2507 }
2512 2508
2513 const Class& cls = Class::ZoneHandle(node->constructor().owner()); 2509 const Class& cls = Class::ZoneHandle(node->constructor().owner());
2514 const bool requires_type_arguments = cls.HasTypeArguments(); 2510 const bool requires_type_arguments = cls.HasTypeArguments();
2515 GenerateTypeArguments(node, requires_type_arguments); 2511 const bool instantiate_type_arguments = false; // Done in stub or runtime.
2512 if (requires_type_arguments) {
2513 GenerateTypeArguments(node->id(),
2514 node->token_index(),
2515 node->type_arguments(),
2516 instantiate_type_arguments);
2517 }
2516 2518
2517 // If cls is parameterized, the type arguments and the instantiator's 2519 // If cls is parameterized, the type arguments and the instantiator's
2518 // type arguments are on the stack. 2520 // type arguments are on the stack.
2519 // In checked mode, if the type arguments are uninstantiated, they may need to 2521 // In checked mode, if the type arguments are uninstantiated, they may need to
2520 // be checked against declared bounds at run time. 2522 // be checked against declared bounds at run time.
2521 Error& malformed_error = Error::Handle(); 2523 Error& malformed_error = Error::Handle();
2522 if (FLAG_enable_type_checks && 2524 if (FLAG_enable_type_checks &&
2523 requires_type_arguments && 2525 requires_type_arguments &&
2524 !node->type_arguments().IsNull() && 2526 !node->type_arguments().IsNull() &&
2525 !node->type_arguments().IsInstantiated() && 2527 !node->type_arguments().IsInstantiated() &&
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
2903 const Error& error = Error::Handle( 2905 const Error& error = Error::Handle(
2904 Parser::FormatError(script, token_index, "Error", format, args)); 2906 Parser::FormatError(script, token_index, "Error", format, args));
2905 va_end(args); 2907 va_end(args);
2906 Isolate::Current()->long_jump_base()->Jump(1, error); 2908 Isolate::Current()->long_jump_base()->Jump(1, error);
2907 UNREACHABLE(); 2909 UNREACHABLE();
2908 } 2910 }
2909 2911
2910 } // namespace dart 2912 } // namespace dart
2911 2913
2912 #endif // defined TARGET_ARCH_IA32 2914 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698