Version 0.6.8.0 .
svn merge -r 25191:25219 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@25221 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/http/test/safe_http_server.dart b/pkg/http/test/safe_http_server.dart
index 0f3b9f1..e55834c 100644
--- a/pkg/http/test/safe_http_server.dart
+++ b/pkg/http/test/safe_http_server.dart
@@ -30,7 +30,7 @@
: super(server),
_inner = server;
- void close() => _inner.close();
+ Future close() => _inner.close();
int get port => _inner.port;
diff --git a/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart b/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
index 0f3b9f1..e55834c 100644
--- a/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
+++ b/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
@@ -30,7 +30,7 @@
: super(server),
_inner = server;
- void close() => _inner.close();
+ Future close() => _inner.close();
int get port => _inner.port;
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index e75250f..8a26043 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -20,6 +20,7 @@
kOutEvent = 1,
kErrorEvent = 2,
kCloseEvent = 3,
+ kDestroyedEvent = 4,
kCloseCommand = 8,
kShutdownReadCommand = 9,
kShutdownWriteCommand = 10,
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 594a6db..258a96b 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -224,6 +224,7 @@
}
socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
delete sd;
+ DartUtils::PostInt32(msg.dart_port, 1 << kDestroyedEvent);
} else {
// Setup events to wait for.
sd->SetPortAndMask(msg.dart_port, msg.data);
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 2b62391..cae7403 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -233,6 +233,7 @@
}
socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
delete sd;
+ DartUtils::PostInt32(msg.dart_port, 1 << kDestroyedEvent);
} else {
if ((msg.data & (1 << kInEvent)) != 0 && sd->IsClosedRead()) {
DartUtils::PostInt32(msg.dart_port, 1 << kCloseEvent);
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index 9a60d6f..1570015 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -244,6 +244,7 @@
}
socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
delete sd;
+ DartUtils::PostInt32(msg.dart_port, 1 << kDestroyedEvent);
} else {
if ((msg.data & (1 << kInEvent)) != 0 && sd->IsClosedRead()) {
DartUtils::PostInt32(msg.dart_port, 1 << kCloseEvent);
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 332f80f..3ced5d0 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -324,7 +324,7 @@
bool FileHandle::IsClosed() {
- return false;
+ return IsClosing();
}
@@ -573,7 +573,7 @@
void ClientSocket::DoClose() {
- // Always do a suhtdown before initiating a disconnect.
+ // Always do a shutdown before initiating a disconnect.
shutdown(socket(), SD_BOTH);
IssueDisconnect();
}
@@ -630,12 +630,14 @@
void ClientSocket::IssueDisconnect() {
+ Dart_Port p = port();
IOBuffer* buffer = IOBuffer::AllocateDisconnectBuffer();
BOOL ok = DisconnectEx_(
socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0);
if (!ok && WSAGetLastError() != WSA_IO_PENDING) {
DisconnectComplete(buffer);
}
+ if (p != ILLEGAL_PORT) DartUtils::PostInt32(p, 1 << kDestroyedEvent);
}
@@ -666,6 +668,15 @@
}
+static void DeleteIfClosed(Handle* handle) {
+ if (handle->IsClosed()) {
+ Dart_Port port = handle->port();
+ delete handle;
+ DartUtils::PostInt32(port, 1 << kDestroyedEvent);
+ }
+}
+
+
void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) {
if (msg->id == kTimeoutId) {
// Change of timeout request. Just set the new timeout and port as the
@@ -674,7 +685,6 @@
} else if (msg->id == kShutdownId) {
shutdown_ = true;
} else {
- bool delete_handle = false;
Handle* handle = reinterpret_cast<Handle*>(msg->id);
ASSERT(handle != NULL);
if (handle->is_listen_socket()) {
@@ -701,9 +711,6 @@
if ((msg->data & (1 << kCloseCommand)) != 0) {
listen_socket->Close();
- if (listen_socket->IsClosed()) {
- delete_handle = true;
- }
}
} else {
handle->EnsureInitialized(this);
@@ -756,15 +763,11 @@
}
if ((msg->data & (1 << kCloseCommand)) != 0) {
+ handle->SetPortAndMask(msg->dart_port, msg->data);
handle->Close();
- if (handle->IsClosed()) {
- delete_handle = true;
- }
}
}
- if (delete_handle) {
- delete handle;
- }
+ DeleteIfClosed(handle);
}
}
@@ -780,9 +783,7 @@
}
}
- if (listen_socket->IsClosed()) {
- delete listen_socket;
- }
+ DeleteIfClosed(listen_socket);
}
@@ -825,9 +826,7 @@
}
}
- if (handle->IsClosed()) {
- delete handle;
- }
+ DeleteIfClosed(handle);
}
@@ -849,9 +848,7 @@
HandleError(handle);
}
- if (handle->IsClosed()) {
- delete handle;
- }
+ DeleteIfClosed(handle);
}
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 4cd6745..a3cc62b 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -172,8 +172,9 @@
static const int WRITE_EVENT = 1;
static const int ERROR_EVENT = 2;
static const int CLOSED_EVENT = 3;
+ static const int DESTROYED_EVENT = 4;
static const int FIRST_EVENT = READ_EVENT;
- static const int LAST_EVENT = CLOSED_EVENT;
+ static const int LAST_EVENT = DESTROYED_EVENT;
static const int EVENT_COUNT = LAST_EVENT - FIRST_EVENT + 1;
static const int CLOSE_COMMAND = 8;
@@ -197,6 +198,7 @@
// Socket close state
bool isClosed = false;
+ bool isClosing = false;
bool isClosedRead = false;
bool isClosedWrite = false;
Completer closeCompleter = new Completer();
@@ -370,7 +372,7 @@
}
int available() {
- if (isClosed) return 0;
+ if (isClosing || isClosed) return 0;
var result = nativeAvailable();
if (result is OSError) {
reportError(result, "Available failed");
@@ -384,7 +386,7 @@
if (len != null && len <= 0) {
throw new ArgumentError("Illegal length $len");
}
- if (isClosed) return null;
+ if (isClosing || isClosed) return null;
var result = nativeRead(len == null ? -1 : len);
if (result is OSError) {
reportError(result, "Read failed");
@@ -410,7 +412,7 @@
if (offset is! int || bytes is! int) {
throw new ArgumentError("Invalid arguments to write on Socket");
}
- if (isClosed) return 0;
+ if (isClosing || isClosed) return 0;
if (bytes == 0) return 0;
_BufferAndStart bufferAndStart =
_ensureFastAndSerializableByteData(buffer, offset, offset + bytes);
@@ -451,11 +453,20 @@
if (((events & (1 << i)) != 0)) {
if (i == CLOSED_EVENT &&
typeFlags != TYPE_LISTENING_SOCKET &&
+ !isClosing &&
!isClosed) {
isClosedRead = true;
}
var handler = eventHandlers[i];
+ if (i == DESTROYED_EVENT) {
+ assert(!isClosed);
+ isClosed = true;
+ closeCompleter.complete(this);
+ disconnectFromEventHandler();
+ if (handler != null) handler();
+ continue;
+ }
assert(handler != null);
if (i == WRITE_EVENT) {
// If the event was disabled before we had a chance to fire the event,
@@ -486,11 +497,12 @@
activateHandlers();
}
- void setHandlers({read: null, write: null, error: null, closed: null}) {
+ void setHandlers({read, write, error, closed, destroyed}) {
eventHandlers[READ_EVENT] = read;
eventHandlers[WRITE_EVENT] = write;
eventHandlers[ERROR_EVENT] = error;
eventHandlers[CLOSED_EVENT] = closed;
+ eventHandlers[DESTROYED_EVENT] = destroyed;
}
void setListening({read: true, write: true}) {
@@ -500,37 +512,34 @@
activateHandlers();
}
- Future get closeFuture => closeCompleter.future;
+ Future<_NativeSocket> get closeFuture => closeCompleter.future;
void activateHandlers() {
- if (canActivateEvents && !isClosed) {
- // If we don't listen for either read or write, disconnect as we won't
- // get close and error events anyway.
+ if (canActivateEvents && !isClosing && !isClosed) {
if ((eventMask & ((1 << READ_EVENT) | (1 << WRITE_EVENT))) == 0) {
+ // If we don't listen for either read or write, disconnect as we won't
+ // get close and error events anyway.
if (eventPort != null) disconnectFromEventHandler();
} else {
int data = eventMask;
- data |= typeFlags;
if (isClosedRead) data &= ~(1 << READ_EVENT);
if (isClosedWrite) data &= ~(1 << WRITE_EVENT);
+ data |= typeFlags;
sendToEventHandler(data);
}
}
}
- void close() {
- if (!isClosed) {
+ Future<_NativeSocket> close() {
+ if (!isClosing && !isClosed) {
sendToEventHandler(1 << CLOSE_COMMAND);
- isClosed = true;
- closeCompleter.complete(this);
+ isClosing = true;
}
- // Outside the if support closing sockets created but never
- // assigned any actual socket.
- disconnectFromEventHandler();
+ return closeFuture;
}
void shutdown(SocketDirection direction) {
- if (!isClosed) {
+ if (!isClosing && !isClosed) {
switch (direction) {
case SocketDirection.RECEIVE:
shutdownRead();
@@ -548,7 +557,7 @@
}
void shutdownWrite() {
- if (!isClosed) {
+ if (!isClosing && !isClosed) {
if (isClosedRead) {
close();
} else {
@@ -559,7 +568,7 @@
}
void shutdownRead() {
- if (!isClosed) {
+ if (!isClosing && !isClosed) {
if (isClosedWrite) {
close();
} else {
@@ -709,7 +718,7 @@
int get port => _socket.port;
- void close() => _socket.close();
+ Future close() => _socket.close().then((_) => this);
void _pause() {
_socket.setListening(read: false, write: false);
@@ -768,6 +777,7 @@
_controller.add(RawSocketEvent.WRITE);
},
closed: () => _controller.add(RawSocketEvent.READ_CLOSED),
+ destroyed: () => _controller.add(RawSocketEvent.CLOSED),
error: (e) {
_controller.addError(e);
close();
@@ -825,7 +835,7 @@
int write(List<int> buffer, [int offset, int count]) =>
_socket.write(buffer, offset, count);
- void close() => _socket.close();
+ Future close() => _socket.close().then((_) => this);
void shutdown(SocketDirection direction) => _socket.shutdown(direction);
@@ -918,7 +928,7 @@
int get port => _socket.port;
- void close() => _socket.close();
+ Future close() => _socket.close().then((_) => this);
}
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index b8b3546..149ec50 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -422,7 +422,6 @@
static Dart_Handle CreateTypedefMirror(Dart_Handle cls,
Dart_Handle cls_name,
- Dart_Handle owner,
Dart_Handle owner_mirror) {
Dart_Handle mirror_cls_name = NewString("_LocalTypedefMirrorImpl");
Dart_Handle mirror_type = Dart_GetType(MirrorLib(), mirror_cls_name, 0, NULL);
@@ -451,16 +450,14 @@
static Dart_Handle CreateConstructorMap(Dart_Handle owner,
Dart_Handle owner_mirror);
-
static Dart_Handle CreateClassMirrorUsingApi(Dart_Handle intf,
Dart_Handle intf_name,
- Dart_Handle lib,
Dart_Handle lib_mirror) {
ASSERT(Dart_IsClass(intf));
if (Dart_ClassIsTypedef(intf)) {
// This class is actually a typedef. Represent it specially in
// reflection.
- return CreateTypedefMirror(intf, intf_name, lib, lib_mirror);
+ return CreateTypedefMirror(intf, intf_name, lib_mirror);
}
Dart_Handle cls_name = NewString("_LocalClassMirrorImpl");
@@ -613,7 +610,7 @@
return intf;
}
Dart_Handle intf_mirror =
- CreateClassMirrorUsingApi(intf, intf_name, owner, owner_mirror);
+ CreateClassMirrorUsingApi(intf, intf_name, owner_mirror);
if (Dart_IsError(intf_mirror)) {
return intf_mirror;
}
@@ -972,6 +969,7 @@
static RawInstance* CreateClassMirror(const Class& cls,
const Instance& owner_mirror) {
+ Instance& retvalue = Instance::Handle();
Dart_EnterScope();
Isolate* isolate = Isolate::Current();
Dart_Handle cls_handle = Api::NewHandle(isolate, cls.raw());
@@ -982,30 +980,23 @@
if (Dart_IsError(name_handle)) {
Dart_PropagateError(name_handle);
}
- Dart_Handle lib_handle = Api::NewHandle(isolate, cls.library());
- if (Dart_IsError(lib_handle)) {
- Dart_PropagateError(lib_handle);
- }
- Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib_handle);
- if (Dart_IsError(lib_mirror)) {
- Dart_PropagateError(lib_mirror);
- }
+ Dart_Handle lib_mirror = Api::NewHandle(isolate, owner_mirror.raw());
// TODO(11742): At some point the handle calls will be replaced by inlined
// functionality.
Dart_Handle result = CreateClassMirrorUsingApi(cls_handle,
name_handle,
- lib_handle,
lib_mirror);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
- const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+ retvalue ^= Api::UnwrapHandle(result);
Dart_ExitScope();
return retvalue.raw();
}
static RawInstance* CreateLibraryMirror(const Library& lib) {
+ Instance& retvalue = Instance::Handle();
Dart_EnterScope();
Isolate* isolate = Isolate::Current();
Dart_Handle lib_handle = Api::NewHandle(isolate, lib.raw());
@@ -1015,7 +1006,7 @@
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
- const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+ retvalue ^= Api::UnwrapHandle(result);
Dart_ExitScope();
return retvalue.raw();
}
@@ -1023,6 +1014,7 @@
static RawInstance* CreateMethodMirror(const Function& func,
const Instance& owner_mirror) {
+ Instance& retvalue = Instance::Handle();
Dart_EnterScope();
Isolate* isolate = Isolate::Current();
Dart_Handle func_handle = Api::NewHandle(isolate, func.raw());
@@ -1033,7 +1025,7 @@
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
- const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+ retvalue ^= Api::UnwrapHandle(result);
Dart_ExitScope();
return retvalue.raw();
}
@@ -1082,17 +1074,9 @@
if (Dart_IsError(name_handle)) {
Dart_PropagateError(name_handle);
}
- Dart_Handle lib_handle = Api::NewHandle(isolate, cls.library());
- if (Dart_IsError(lib_handle)) {
- Dart_PropagateError(lib_handle);
- }
- Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib_handle);
- if (Dart_IsError(lib_mirror)) {
- Dart_PropagateError(lib_mirror);
- }
+ Dart_Handle lib_mirror = Dart_Null();
Dart_Handle result = CreateClassMirrorUsingApi(cls_handle,
name_handle,
- lib_handle,
lib_mirror);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
@@ -1263,6 +1247,16 @@
}
+DEFINE_NATIVE_ENTRY(ClassMirror_library, 1) {
+ const MirrorReference& klass_ref =
+ MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
+ Class& klass = Class::Handle();
+ klass ^= klass_ref.referent();
+
+ return CreateLibraryMirror(Library::Handle(klass.library()));
+}
+
+
// Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
// exceptions. Wrap and propagate any compilation errors.
static RawObject* ReflectivelyInvokeDynamicFunction(const Instance& receiver,
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 542e6e8..450aa2d 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -422,7 +422,10 @@
var _owner;
DeclarationMirror get owner {
- if (_owner != null && _owner is! Mirror) {
+ if (_owner == null) {
+ _owner = _library(_reflectee);
+ }
+ if (_owner is! Mirror) {
_owner = _owner.resolve(mirrors);
}
return _owner;
@@ -573,6 +576,9 @@
static _name(reflectee)
native "ClassMirror_name";
+ static _library(reflectee)
+ native "ClassMirror_library";
+
_invoke(reflectee, memberName, positionalArguments)
native 'ClassMirror_invoke';
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index d7912dc..5bf8ad1 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -244,6 +244,7 @@
V(InstanceMirror_invokeSetter, 4) \
V(ClosureMirror_apply, 2) \
V(ClassMirror_name, 1) \
+ V(ClassMirror_library, 1) \
V(ClassMirror_invoke, 4) \
V(ClassMirror_invokeGetter, 3) \
V(ClassMirror_invokeSetter, 4) \
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 6665626..746ca35 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -3094,22 +3094,30 @@
Value* allocated_context =
Bind(new AllocateContextInstr(node->token_pos(),
num_context_variables));
-
- // If this node_sequence is the body of the function being compiled, and if
- // this function allocates context variables, but none of its enclosing
- // functions do, the context on entry is not linked as parent of the
- // allocated context but saved on entry and restored on exit as to prevent
- // memory leaks.
- // In this case, the parser pre-allocates a variable to save the context.
- if (MustSaveRestoreContext(node)) {
+ { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context);
+ // If this node_sequence is the body of the function being compiled, and
+ // if this function allocates context variables, but none of its enclosing
+ // functions do, the context on entry is not linked as parent of the
+ // allocated context but saved on entry and restored on exit as to prevent
+ // memory leaks.
+ // In this case, the parser pre-allocates a variable to save the context.
+ if (MustSaveRestoreContext(node)) {
+ Value* current_context = Bind(new CurrentContextInstr());
+ Do(BuildStoreTemp(
+ *owner()->parsed_function()->saved_entry_context_var(),
+ current_context));
+ Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle()));
+ AddInstruction(new StoreContextInstr(null_context));
+ }
Value* current_context = Bind(new CurrentContextInstr());
- Do(BuildStoreTemp(*owner()->parsed_function()->saved_entry_context_var(),
- current_context));
- Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle()));
- AddInstruction(new StoreContextInstr(null_context));
+ Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var));
+ Do(new StoreVMFieldInstr(tmp_val,
+ Context::parent_offset(),
+ current_context,
+ Type::ZoneHandle()));
+ AddInstruction(
+ new StoreContextInstr(Bind(ExitTempLocalScope(tmp_var))));
}
-
- AddInstruction(new ChainContextInstr(allocated_context));
owner()->set_context_level(scope->context_level());
// If this node_sequence is the body of the function being compiled, copy
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index a350e07..e3a1f82 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -3793,7 +3793,6 @@
*is_load = true;
break;
- case Instruction::kChainContext:
case Instruction::kStoreContext:
kind_ = kContext;
break;
@@ -4019,7 +4018,7 @@
return Alias::VMField(store_vm_field->offset_in_bytes());
}
- if (instr->IsStoreContext() || instr->IsChainContext()) {
+ if (instr->IsStoreContext()) {
return Alias::CurrentContext();
}
@@ -4261,7 +4260,7 @@
return store_static_field->value()->definition();
}
- if (instr->IsStoreContext() || instr->IsChainContext()) {
+ if (instr->IsStoreContext()) {
return instr->InputAt(0)->definition();
}
@@ -5512,9 +5511,6 @@
void ConstantPropagator::VisitStoreContext(StoreContextInstr* instr) { }
-void ConstantPropagator::VisitChainContext(ChainContextInstr* instr) { }
-
-
void ConstantPropagator::VisitCatchEntry(CatchEntryInstr* instr) { }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 49d2a54..bc01952 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -565,7 +565,6 @@
M(ExtractConstructorTypeArguments) \
M(ExtractConstructorInstantiator) \
M(AllocateContext) \
- M(ChainContext) \
M(CloneContext) \
M(CatchEntry) \
M(BinarySmiOp) \
@@ -4248,29 +4247,6 @@
};
-class ChainContextInstr : public TemplateInstruction<1> {
- public:
- explicit ChainContextInstr(Value* context_value) {
- SetInputAt(0, context_value);
- }
-
- DECLARE_INSTRUCTION(ChainContext)
-
- virtual intptr_t ArgumentCount() const { return 0; }
-
- Value* context_value() const { return inputs_[0]; }
-
- virtual bool CanDeoptimize() const { return false; }
-
- virtual EffectSet Effects() const { return EffectSet::None(); }
-
- virtual bool MayThrow() const { return false; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ChainContextInstr);
-};
-
-
class CloneContextInstr : public TemplateDefinition<1> {
public:
CloneContextInstr(intptr_t token_pos, Value* context_value)
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 87fba15..8d95969 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -3071,13 +3071,47 @@
LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister left = locs()->in(0).fpu_reg();
+ QRegister right = locs()->in(1).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ switch (op_kind()) {
+ case MethodRecognizer::kFloat32x4Equal:
+ __ vceqqs(result, left, right);
+ break;
+ case MethodRecognizer::kFloat32x4NotEqual:
+ __ vceqqs(result, left, right);
+ // Invert the result.
+ __ veorq(QTMP, QTMP, QTMP); // QTMP <- 0.
+ __ vornq(result, QTMP, result); // result <- ~result.
+ break;
+ case MethodRecognizer::kFloat32x4GreaterThan:
+ __ vcgtqs(result, left, right);
+ break;
+ case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
+ __ vcgeqs(result, left, right);
+ break;
+ case MethodRecognizer::kFloat32x4LessThan:
+ __ vcgtqs(result, right, left);
+ break;
+ case MethodRecognizer::kFloat32x4LessThanOrEqual:
+ __ vcgeqs(result, right, left);
+ break;
+
+ default: UNREACHABLE();
+ }
}
@@ -3137,13 +3171,49 @@
LocationSummary* Float32x4WithInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister replacement = locs()->in(0).fpu_reg();
+ QRegister value = locs()->in(1).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ DRegister dresult0 = EvenDRegisterOf(result);
+ DRegister dresult1 = OddDRegisterOf(result);
+ SRegister sresult0 = EvenSRegisterOf(dresult0);
+ SRegister sresult1 = OddSRegisterOf(dresult0);
+ SRegister sresult2 = EvenSRegisterOf(dresult1);
+ SRegister sresult3 = OddSRegisterOf(dresult1);
+
+ __ vcvtsd(STMP, EvenDRegisterOf(replacement));
+ if (result != value) {
+ __ vmovq(result, value);
+ }
+
+ switch (op_kind()) {
+ case MethodRecognizer::kFloat32x4WithX:
+ __ vmovs(sresult0, STMP);
+ break;
+ case MethodRecognizer::kFloat32x4WithY:
+ __ vmovs(sresult1, STMP);
+ break;
+ case MethodRecognizer::kFloat32x4WithZ:
+ __ vmovs(sresult2, STMP);
+ break;
+ case MethodRecognizer::kFloat32x4WithW:
+ __ vmovs(sresult3, STMP);
+ break;
+ default: UNREACHABLE();
+ }
}
@@ -3170,15 +3240,49 @@
LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresRegister());
+ return summary;
}
void Uint32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister value = locs()->in(0).fpu_reg();
+ Register result = locs()->out().reg();
+
+ DRegister dvalue0 = EvenDRegisterOf(value);
+ DRegister dvalue1 = OddDRegisterOf(value);
+ SRegister svalue0 = EvenSRegisterOf(dvalue0);
+ SRegister svalue1 = OddSRegisterOf(dvalue0);
+ SRegister svalue2 = EvenSRegisterOf(dvalue1);
+ SRegister svalue3 = OddSRegisterOf(dvalue1);
+
+ switch (op_kind()) {
+ case MethodRecognizer::kUint32x4GetFlagX:
+ __ vmovrs(result, svalue0);
+ break;
+ case MethodRecognizer::kUint32x4GetFlagY:
+ __ vmovrs(result, svalue1);
+ break;
+ case MethodRecognizer::kUint32x4GetFlagZ:
+ __ vmovrs(result, svalue2);
+ break;
+ case MethodRecognizer::kUint32x4GetFlagW:
+ __ vmovrs(result, svalue3);
+ break;
+ default: UNREACHABLE();
+ }
+
+ __ tst(result, ShifterOperand(result));
+ __ LoadObject(result, Bool::True(), NE);
+ __ LoadObject(result, Bool::False(), EQ);
}
+
LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const {
UNIMPLEMENTED();
return NULL;
@@ -3875,25 +3979,6 @@
}
-LocationSummary* ChainContextInstr::MakeLocationSummary() const {
- return LocationSummary::Make(1,
- Location::NoLocation(),
- LocationSummary::kNoCall);
-}
-
-
-void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register context_value = locs()->in(0).reg();
-
- // Chain the new context in context_value to its parent in CTX.
- __ StoreIntoObject(context_value,
- FieldAddress(context_value, Context::parent_offset()),
- CTX);
- // Set new context as current context.
- __ mov(CTX, ShifterOperand(context_value));
-}
-
-
LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 532be75..0f4e24b 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -4700,25 +4700,6 @@
}
-LocationSummary* ChainContextInstr::MakeLocationSummary() const {
- return LocationSummary::Make(1,
- Location::NoLocation(),
- LocationSummary::kNoCall);
-}
-
-
-void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register context_value = locs()->in(0).reg();
-
- // Chain the new context in context_value to its parent in CTX.
- __ StoreIntoObject(context_value,
- FieldAddress(context_value, Context::parent_offset()),
- CTX);
- // Set new context as current context.
- __ MoveRegister(CTX, context_value);
-}
-
-
LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 6b8b215..7015a13 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -3713,25 +3713,6 @@
}
-LocationSummary* ChainContextInstr::MakeLocationSummary() const {
- return LocationSummary::Make(1,
- Location::NoLocation(),
- LocationSummary::kNoCall);
-}
-
-
-void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register context_value = locs()->in(0).reg();
-
- // Chain the new context in context_value to its parent in CTX.
- __ StoreIntoObject(context_value,
- FieldAddress(context_value, Context::parent_offset()),
- CTX);
- // Set new context as current context.
- __ mov(CTX, context_value);
-}
-
-
LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 79ab510..a320b95 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -4370,25 +4370,6 @@
}
-LocationSummary* ChainContextInstr::MakeLocationSummary() const {
- return LocationSummary::Make(1,
- Location::NoLocation(),
- LocationSummary::kNoCall);
-}
-
-
-void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register context_value = locs()->in(0).reg();
-
- // Chain the new context in context_value to its parent in CTX.
- __ StoreIntoObject(context_value,
- FieldAddress(context_value, Context::parent_offset()),
- CTX);
- // Set new context as current context.
- __ MoveRegister(CTX, context_value);
-}
-
-
LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 3a9154a..0104ffb 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1679,11 +1679,13 @@
String superName,
{ bool classIsNative: false,
bool emitStatics: false }) {
- assert(superName != null);
- String separator = '';
- String nativeName = namer.getPrimitiveInterceptorRuntimeName(classElement);
StringBuffer buffer = new StringBuffer();
- if (!emitStatics) {
+ if (emitStatics) {
+ assert(invariant(classElement, superName == null, message: superName));
+ } else {
+ assert(invariant(classElement, superName != null));
+ String nativeName =
+ namer.getPrimitiveInterceptorRuntimeName(classElement);
if (nativeName != null) {
buffer.write('$nativeName/');
}
@@ -1691,6 +1693,8 @@
}
int bufferClassLength = buffer.length;
+ String separator = '';
+
var fieldMetadata = [];
bool hasMetadata = false;
@@ -1833,16 +1837,25 @@
emitSuper(superName, builder);
emitRuntimeName(runtimeName, builder);
emitClassFields(classElement, builder, superName);
- var metadata = buildMetadataFunction(classElement);
- if (metadata != null) {
- builder.addProperty("@", metadata);
- }
emitClassGettersSetters(classElement, builder);
if (!classElement.isMixinApplication) {
emitInstanceMembers(classElement, builder);
}
emitIsTests(classElement, builder);
+ emitClassBuilderWithReflectionData(
+ className, classElement, builder, buffer);
+ }
+
+ void emitClassBuilderWithReflectionData(String className,
+ ClassElement classElement,
+ ClassBuilder builder,
+ CodeBuffer buffer) {
+ var metadata = buildMetadataFunction(classElement);
+ if (metadata != null) {
+ builder.addProperty("@", metadata);
+ }
+
List<CodeBuffer> classBuffers = elementBuffers[classElement];
if (classBuffers == null) {
classBuffers = [];
@@ -1854,7 +1867,7 @@
bool hasStatics = false;
ClassBuilder staticsBuilder = new ClassBuilder();
if (emitClassFields(
- classElement, staticsBuilder, superName, emitStatics: true)) {
+ classElement, staticsBuilder, null, emitStatics: true)) {
hasStatics = true;
statics.write('"":$_');
statics.write(
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index 6538cf2..4440c06 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -232,14 +232,11 @@
// Emit the native class interceptors that were actually used.
for (ClassElement classElement in classes) {
if (neededClasses.contains(classElement)) {
- ClassBuilder builder = builders[classElement];
// Define interceptor class for [classElement].
- String className = backend.namer.getName(classElement);
- jsAst.Expression init =
- js(emitter.classesCollector)[className].assign(
- builder.toObjectInitializer());
- mainBuffer.write(jsAst.prettyPrint(init, compiler));
- mainBuffer.write('$N$n');
+ emitter.emitClassBuilderWithReflectionData(
+ backend.namer.getName(classElement),
+ classElement, builders[classElement],
+ emitter.bufferForElement(classElement, mainBuffer));
emitter.needsDefineClass = true;
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 12f9cae..3ae9aa1 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -1087,7 +1087,8 @@
final bool isImplicitSuperCall = false;
final SourceString className = lookupTarget.name;
- verifyThatConstructorMatchesCall(calledConstructor,
+ verifyThatConstructorMatchesCall(constructor,
+ calledConstructor,
selector,
isImplicitSuperCall,
call,
@@ -1124,7 +1125,8 @@
final SourceString className = lookupTarget.name;
final bool isImplicitSuperCall = true;
- verifyThatConstructorMatchesCall(calledConstructor,
+ verifyThatConstructorMatchesCall(constructor,
+ calledConstructor,
callToMatch,
isImplicitSuperCall,
functionNode,
@@ -1136,6 +1138,7 @@
}
void verifyThatConstructorMatchesCall(
+ FunctionElement caller,
FunctionElement lookedupConstructor,
Selector call,
bool isImplicitSuperCall,
@@ -1159,6 +1162,10 @@
? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
: MessageKind.NO_MATCHING_CONSTRUCTOR;
visitor.compiler.reportErrorCode(diagnosticNode, kind);
+ } else if (caller.modifiers.isConst()
+ && !lookedupConstructor.modifiers.isConst()) {
+ visitor.compiler.reportErrorCode(
+ diagnosticNode, MessageKind.CONST_CALLS_NON_CONST);
}
}
}
@@ -3252,7 +3259,7 @@
DartType supertype = resolveSupertype(element, superMixin.superclass);
Link<Node> link = superMixin.mixins.nodes;
while (!link.isEmpty) {
- supertype = applyMixin(supertype, resolveType(link.head));
+ supertype = applyMixin(supertype, resolveType(link.head), node);
link = link.tail;
}
element.supertype = supertype;
@@ -3314,21 +3321,21 @@
DartType supertype = resolveSupertype(element, node.superclass);
Link<Node> link = node.mixins.nodes;
while (!link.tail.isEmpty) {
- supertype = applyMixin(supertype, resolveType(link.head));
+ supertype = applyMixin(supertype, resolveType(link.head), link.head);
link = link.tail;
}
doApplyMixinTo(element, supertype, resolveType(link.head));
return element.computeType(compiler);
}
- DartType applyMixin(DartType supertype, DartType mixinType) {
+ DartType applyMixin(DartType supertype, DartType mixinType, Node node) {
String superName = supertype.name.slowToString();
String mixinName = mixinType.name.slowToString();
ClassElement mixinApplication = new MixinApplicationElementX(
new SourceString("${superName}_${mixinName}"),
element.getCompilationUnit(),
compiler.getNextFreeClassId(),
- element.parseNode(compiler),
+ node,
Modifiers.EMPTY); // TODO(kasperl): Should this be abstract?
doApplyMixinTo(mixinApplication, supertype, mixinType);
mixinApplication.resolutionState = STATE_DONE;
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index 7b016b8..1c05b77 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -591,17 +591,41 @@
/**
* Constant representing [:ConcreteList#[]:] where [:ConcreteList:] is the
- * concrete implmentation of lists for the selected backend.
+ * concrete implementation of lists for the selected backend.
*/
FunctionElement listIndex;
/**
* Constant representing [:ConcreteList#[]=:] where [:ConcreteList:] is the
- * concrete implmentation of lists for the selected backend.
+ * concrete implementation of lists for the selected backend.
*/
FunctionElement listIndexSet;
/**
+ * Constant representing [:ConcreteList#add:] where [:ConcreteList:] is the
+ * concrete implementation of lists for the selected backend.
+ */
+ FunctionElement listAdd;
+
+ /**
+ * Constant representing [:ConcreteList#removeAt:] where [:ConcreteList:] is
+ * the concrete implementation of lists for the selected backend.
+ */
+ FunctionElement listRemoveAt;
+
+ /**
+ * Constant representing [:ConcreteList#insert:] where [:ConcreteList:] is
+ * the concrete implementation of lists for the selected backend.
+ */
+ FunctionElement listInsert;
+
+ /**
+ * Constant representing [:ConcreteList#removeLast:] where [:ConcreteList:] is
+ * the concrete implementation of lists for the selected backend.
+ */
+ FunctionElement listRemoveLast;
+
+ /**
* Constant representing [:List():].
*/
FunctionElement listConstructor;
@@ -1273,16 +1297,15 @@
}
}
- if (function == listIndex) {
- ConcreteType indexType = environment.lookupType(
- listIndex.functionSignature.requiredParameters.head);
+ if (function == listIndex || function == listRemoveAt) {
+ Link<Element> parameters = function.functionSignature.requiredParameters;
+ ConcreteType indexType = environment.lookupType(parameters.head);
if (!indexType.baseTypes.contains(baseTypes.intBaseType)) {
return emptyConcreteType;
}
return listElementType;
- } else if (function == listIndexSet) {
- Link<Element> parameters =
- listIndexSet.functionSignature.requiredParameters;
+ } else if (function == listIndexSet || function == listInsert) {
+ Link<Element> parameters = function.functionSignature.requiredParameters;
ConcreteType indexType = environment.lookupType(parameters.head);
if (!indexType.baseTypes.contains(baseTypes.intBaseType)) {
return emptyConcreteType;
@@ -1290,6 +1313,13 @@
ConcreteType elementType = environment.lookupType(parameters.tail.head);
augmentListElementType(elementType);
return emptyConcreteType;
+ } else if (function == listAdd) {
+ Link<Element> parameters = function.functionSignature.requiredParameters;
+ ConcreteType elementType = environment.lookupType(parameters.head);
+ augmentListElementType(elementType);
+ return emptyConcreteType;
+ } else if (function == listRemoveLast) {
+ return listElementType;
}
return null;
}
@@ -1446,6 +1476,11 @@
ClassElement jsArrayClass = baseTypes.listBaseType.element;
listIndex = jsArrayClass.lookupMember(const SourceString('[]'));
listIndexSet = jsArrayClass.lookupMember(const SourceString('[]='));
+ listAdd = jsArrayClass.lookupMember(const SourceString('add'));
+ listRemoveAt = jsArrayClass.lookupMember(const SourceString('removeAt'));
+ listInsert = jsArrayClass.lookupMember(const SourceString('insert'));
+ listRemoveLast =
+ jsArrayClass.lookupMember(const SourceString('removeLast'));
List<SourceString> typePreservingOps = const [const SourceString('+'),
const SourceString('-'),
const SourceString('*')];
@@ -1543,6 +1578,8 @@
inferredFieldTypes.forEach((k,v) {
print(" $k: $v");
});
+ print("listElementType:");
+ print(" $listElementType");
print("inferredParameterTypes:");
inferredParameterTypes.forEach((k,v) {
print(" $k: $v");
@@ -1677,7 +1714,16 @@
}
ConcreteType visitDoWhile(DoWhile node) {
- inferrer.fail(node, 'not yet implemented');
+ analyze(node.body);
+ analyze(node.condition);
+ ConcreteTypesEnvironment oldEnvironment;
+ do {
+ oldEnvironment = environment;
+ analyze(node.body);
+ analyze(node.condition);
+ environment = oldEnvironment.join(environment);
+ } while (oldEnvironment != environment);
+ return inferrer.emptyConcreteType;
}
ConcreteType visitExpressionStatement(ExpressionStatement node) {
@@ -1690,7 +1736,6 @@
analyze(node.initializer);
}
analyze(node.conditionStatement);
- ConcreteType result = inferrer.emptyConcreteType;
ConcreteTypesEnvironment oldEnvironment;
do {
oldEnvironment = environment;
@@ -1702,7 +1747,7 @@
// value indicating whether something changed to avoid performing this
// comparison twice.
} while (oldEnvironment != environment);
- return result;
+ return inferrer.emptyConcreteType;
}
void analyzeClosure(FunctionExpression node) {
@@ -2001,7 +2046,6 @@
ConcreteType visitWhile(While node) {
analyze(node.condition);
- ConcreteType result = inferrer.emptyConcreteType;
ConcreteTypesEnvironment oldEnvironment;
do {
oldEnvironment = environment;
@@ -2009,7 +2053,7 @@
analyze(node.body);
environment = oldEnvironment.join(environment);
} while (oldEnvironment != environment);
- return result;
+ return inferrer.emptyConcreteType;
}
ConcreteType visitParenthesizedExpression(ParenthesizedExpression node) {
@@ -2288,8 +2332,8 @@
: environment.lookupTypeOfThis();
SourceString name =
canonicalizeMethodName(node.selector.asIdentifier().source);
- ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
if (name.stringValue == '!=') {
+ ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
ConcreteType returnType = analyzeDynamicSend(elements.getSelector(node),
receiverType,
const SourceString('=='),
@@ -2298,8 +2342,12 @@
? returnType
: inferrer.singletonConcreteType(inferrer.baseTypes.boolBaseType);
} else if (name.stringValue == '&&' || name.stringValue == '||'){
+ ConcreteTypesEnvironment oldEnvironment = environment;
+ analyze(node.arguments.head);
+ environment = oldEnvironment.join(environment);
return inferrer.singletonConcreteType(inferrer.baseTypes.boolBaseType);
} else {
+ ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
return analyzeDynamicSend(elements.getSelector(node),
receiverType, name, argumentsTypes);
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
index 156042e..dc3f3dd 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
@@ -337,17 +337,19 @@
}
}
-class ContainerTracerVisitor extends InferrerVisitor {
+class ContainerTracerVisitor extends InferrerVisitor<TypeMask> {
final Element analyzedElement;
final TracerForConcreteContainer tracer;
final bool visitingClosure;
ContainerTracerVisitor(element, tracer, [LocalsHandler locals])
- : super(element, tracer.inferrer, tracer.compiler, locals),
+ : super(element, tracer.inferrer.types, tracer.compiler, locals),
this.analyzedElement = element,
this.tracer = tracer,
visitingClosure = locals != null;
+ SimpleTypesInferrer get inferrer => tracer.inferrer;
+
bool escaping = false;
bool visitingInitializers = false;
@@ -437,7 +439,7 @@
visitingInitializers = false;
visit(node.body);
}
- return compiler.typesTask.functionType;
+ return types.functionType;
}
TypeMask visitLiteralList(LiteralList node) {
@@ -455,7 +457,7 @@
} else {
node.visitChildren(this);
}
- return compiler.typesTask.growableListType;
+ return types.growableListType;
}
// TODO(ngeoffray): Try to move the following two methods in
@@ -503,7 +505,7 @@
bool isIndexEscaping = false;
bool isValueEscaping = false;
if (isIncrementOrDecrement) {
- rhsType = compiler.typesTask.intType;
+ rhsType = types.intType;
if (node.isIndex) {
isIndexEscaping = visitAndCatchEscaping(() {
indexType = visit(node.arguments.head);
@@ -606,7 +608,7 @@
} else if (element.isFunction()) {
return inferrer.getReturnTypeOfElement(element);
} else {
- return compiler.typesTask.dynamicType;
+ return types.dynamicType;
}
}
@@ -622,7 +624,7 @@
} else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
visitArguments(node.arguments, element);
if (tracer.couldBeTheList(node)) {
- tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
+ tracer.unionPotentialTypeWith(types.nullType);
escaping = true;
LiteralInt length = node.arguments.head.asLiteralInt();
if (length != null) {
@@ -660,7 +662,7 @@
return inferrer.getReturnTypeOfElement(element);
} else {
// Closure call or unresolved.
- return compiler.typesTask.dynamicType;
+ return types.dynamicType;
}
}
@@ -675,9 +677,9 @@
} else if (Elements.isInstanceSend(node, elements)) {
return visitDynamicSend(node);
} else if (Elements.isStaticOrTopLevelFunction(element)) {
- return compiler.typesTask.functionType;
+ return types.functionType;
} else if (Elements.isErroneousElement(element)) {
- return compiler.typesTask.dynamicType;
+ return types.dynamicType;
} else if (Elements.isLocal(element)) {
if (tracer.couldBeTheList(element)) {
escaping = true;
@@ -685,7 +687,7 @@
return locals.use(element);
} else {
node.visitChildren(this);
- return compiler.typesTask.dynamicType;
+ return types.dynamicType;
}
}
@@ -696,7 +698,7 @@
visitArguments(node.arguments, elements.getSelector(node));
if (isEscaping) return tracer.bailout('Passed to a closure');
- return compiler.typesTask.dynamicType;
+ return types.dynamicType;
}
TypeMask visitDynamicSend(Send node) {
@@ -744,7 +746,7 @@
TypeMask visitReturn(Return node) {
if (node.expression == null) {
- return compiler.typesTask.nullType;
+ return types.nullType;
}
TypeMask type;
diff --git a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
index d357a35..12d0ba0 100644
--- a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
@@ -4,50 +4,116 @@
part of simple_types_inferrer;
-TypeMask narrowType(TypeMask type,
- DartType annotation,
- Compiler compiler,
- {bool isNullable: true}) {
- if (annotation.isDynamic) return type;
- if (annotation.isMalformed) return type;
- if (annotation.isVoid) return compiler.typesTask.nullType;
- if (annotation.element == compiler.objectClass) return type;
- TypeMask otherType;
- if (annotation.kind == TypeKind.TYPEDEF
- || annotation.kind == TypeKind.FUNCTION) {
- otherType = compiler.typesTask.functionType;
- } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
- return type;
- } else {
- assert(annotation.kind == TypeKind.INTERFACE);
- otherType = new TypeMask.nonNullSubtype(annotation);
- }
- if (isNullable) otherType = otherType.nullable();
- if (type == null) return otherType;
- return type.intersection(otherType, compiler);
+/**
+ * The interface [InferrerVisitor] will use when working on types.
+ */
+abstract class TypeSystem<T> {
+ T get dynamicType;
+ T get nullType;
+ T get intType;
+ T get doubleType;
+ T get numType;
+ T get boolType;
+ T get functionType;
+ T get listType;
+ T get constListType;
+ T get fixedListType;
+ T get growableListType;
+ T get mapType;
+ T get constMapType;
+ T get stringType;
+ T get typeType;
+
+ T nonNullSubtype(DartType type);
+ T nonNullSubclass(DartType type);
+ T nonNullExact(DartType type);
+
+ /**
+ * Returns the intersection between [T] and [annotation].
+ * [isNullable] indicates whether the annotation implies a null
+ * type.
+ */
+ T narrowType(T type, DartType annotation, {bool isNullable: true});
+
+ /**
+ * Returns the least upper bound between [firstType] and
+ * [secondType].
+ */
+ T computeLUB(T firstType, T secondType);
+
+ /**
+ * Returns the type inferred by the inferrer for [element].
+ */
+ T getTypeOfCapturedAndBoxedVariable(Element element);
}
/**
- * Returns the least upper bound between [firstType] and
- * [secondType].
+ * An implementation of [TypeSystem] for [TypeMask].
*/
-TypeMask computeLUB(TypeMask firstType,
- TypeMask secondType,
- Compiler compiler) {
- TypeMask dynamicType = compiler.typesTask.dynamicType;
- if (firstType == null) {
- return secondType;
- } else if (secondType == dynamicType) {
- return secondType;
- } else if (firstType == dynamicType) {
- return firstType;
- } else if (firstType == secondType) {
- return firstType;
- } else {
- TypeMask union = firstType.union(secondType, compiler);
- // TODO(kasperl): If the union isn't nullable it seems wasteful
- // to use dynamic. Fix that.
- return union.containsAll(compiler) ? dynamicType : union;
+class TypeMaskSystem implements TypeSystem<TypeMask> {
+ final Compiler compiler;
+ TypeMaskSystem(this.compiler);
+
+ TypeMask narrowType(TypeMask type,
+ DartType annotation,
+ {bool isNullable: true}) {
+ if (annotation.isDynamic) return type;
+ if (annotation.isMalformed) return type;
+ if (annotation.isVoid) return nullType;
+ if (annotation.element == compiler.objectClass) return type;
+ TypeMask otherType;
+ if (annotation.kind == TypeKind.TYPEDEF
+ || annotation.kind == TypeKind.FUNCTION) {
+ otherType = functionType;
+ } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
+ // TODO(ngeoffray): Narrow to bound.
+ return type;
+ } else {
+ assert(annotation.kind == TypeKind.INTERFACE);
+ otherType = new TypeMask.nonNullSubtype(annotation);
+ }
+ if (isNullable) otherType = otherType.nullable();
+ if (type == null) return otherType;
+ return type.intersection(otherType, compiler);
+ }
+
+ TypeMask computeLUB(TypeMask firstType, TypeMask secondType) {
+ if (firstType == null) {
+ return secondType;
+ } else if (secondType == dynamicType || firstType == dynamicType) {
+ return dynamicType;
+ } else if (firstType == secondType) {
+ return firstType;
+ } else {
+ TypeMask union = firstType.union(secondType, compiler);
+ // TODO(kasperl): If the union isn't nullable it seems wasteful
+ // to use dynamic. Fix that.
+ return union.containsAll(compiler) ? dynamicType : union;
+ }
+ }
+
+ TypeMask get dynamicType => compiler.typesTask.dynamicType;
+ TypeMask get nullType => compiler.typesTask.nullType;
+ TypeMask get intType => compiler.typesTask.intType;
+ TypeMask get doubleType => compiler.typesTask.doubleType;
+ TypeMask get numType => compiler.typesTask.numType;
+ TypeMask get boolType => compiler.typesTask.boolType;
+ TypeMask get functionType => compiler.typesTask.functionType;
+ TypeMask get listType => compiler.typesTask.listType;
+ TypeMask get constListType => compiler.typesTask.constListType;
+ TypeMask get fixedListType => compiler.typesTask.fixedListType;
+ TypeMask get growableListType => compiler.typesTask.growableListType;
+ TypeMask get mapType => compiler.typesTask.mapType;
+ TypeMask get constMapType => compiler.typesTask.constMapType;
+ TypeMask get stringType => compiler.typesTask.stringType;
+ TypeMask get typeType => compiler.typesTask.typeType;
+
+ TypeMask nonNullSubtype(DartType type) => new TypeMask.nonNullSubtype(type);
+ TypeMask nonNullSubclass(DartType type) => new TypeMask.nonNullSubclass(type);
+ TypeMask nonNullExact(DartType type) => new TypeMask.nonNullExact(type);
+
+ TypeMask getTypeOfCapturedAndBoxedVariable(Element element) {
+ return compiler.typesTask.typesInferrer.getTypeOfElement(element);
}
}
@@ -58,11 +124,11 @@
* The inferrer makes sure updates get merged into the parent scope,
* once the control flow block has been visited.
*/
-class VariableScope {
- Map<Element, TypeMask> variables;
+class VariableScope<T> {
+ Map<Element, T> variables;
/// The parent of this scope. Null for the root scope.
- final VariableScope parent;
+ final VariableScope<T> parent;
/// The block level of this scope. Starts at 0 for the root scope.
final int blockLevel;
@@ -72,32 +138,32 @@
this.parent = parent,
this.blockLevel = parent == null ? 0 : parent.blockLevel + 1;
- VariableScope.deepCopyOf(VariableScope other)
+ VariableScope.deepCopyOf(VariableScope<T> other)
: variables = other.variables == null
? null
- : new Map<Element, TypeMask>.from(other.variables),
+ : new Map<Element, T>.from(other.variables),
blockLevel = other.blockLevel,
parent = other.parent == null
? null
- : new VariableScope.deepCopyOf(other.parent);
+ : new VariableScope<T>.deepCopyOf(other.parent);
- TypeMask operator [](Element variable) {
- TypeMask result;
+ T operator [](Element variable) {
+ T result;
if (variables == null || (result = variables[variable]) == null) {
return parent == null ? null : parent[variable];
}
return result;
}
- void operator []=(Element variable, TypeMask mask) {
+ void operator []=(Element variable, T mask) {
assert(mask != null);
if (variables == null) {
- variables = new Map<Element, TypeMask>();
+ variables = new Map<Element, T>();
}
variables[variable] = mask;
}
- void forEachOwnLocal(void f(Element element, TypeMask mask)) {
+ void forEachOwnLocal(void f(Element element, T type)) {
if (variables == null) return;
variables.forEach(f);
}
@@ -115,12 +181,12 @@
/**
* Placeholder for inferred types of local variables.
*/
-class LocalsHandler {
+class LocalsHandler<T> {
final Compiler compiler;
- final TypesInferrer inferrer;
- final VariableScope locals;
+ final TypeSystem<T> types;
+ final VariableScope<T> locals;
final Map<Element, Element> capturedAndBoxed;
- final Map<Element, TypeMask> fieldsInitializedInConstructor;
+ final Map<Element, T> fieldsInitializedInConstructor;
final bool inTryBlock;
bool isThisExposed;
bool seenReturnOrThrow = false;
@@ -130,46 +196,46 @@
return seenReturnOrThrow || seenBreakOrContinue;
}
- LocalsHandler(this.inferrer, this.compiler)
- : locals = new VariableScope(),
+ LocalsHandler(this.types, this.compiler)
+ : locals = new VariableScope<T>(),
capturedAndBoxed = new Map<Element, Element>(),
- fieldsInitializedInConstructor = new Map<Element, TypeMask>(),
+ fieldsInitializedInConstructor = new Map<Element, T>(),
inTryBlock = false,
isThisExposed = true;
- LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
- : locals = new VariableScope(other.locals),
+ LocalsHandler.from(LocalsHandler<T> other, {bool inTryBlock: false})
+ : locals = new VariableScope<T>(other.locals),
capturedAndBoxed = new Map<Element, Element>.from(
other.capturedAndBoxed),
- fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
+ fieldsInitializedInConstructor = new Map<Element, T>.from(
other.fieldsInitializedInConstructor),
inTryBlock = other.inTryBlock || inTryBlock,
- inferrer = other.inferrer,
+ types = other.types,
compiler = other.compiler,
isThisExposed = other.isThisExposed;
- LocalsHandler.deepCopyOf(LocalsHandler other)
- : locals = new VariableScope.deepCopyOf(other.locals),
+ LocalsHandler.deepCopyOf(LocalsHandler<T> other)
+ : locals = new VariableScope<T>.deepCopyOf(other.locals),
capturedAndBoxed = new Map<Element, Element>.from(
other.capturedAndBoxed),
- fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
+ fieldsInitializedInConstructor = new Map<Element, T>.from(
other.fieldsInitializedInConstructor),
inTryBlock = other.inTryBlock,
- inferrer = other.inferrer,
+ types = other.types,
compiler = other.compiler,
isThisExposed = other.isThisExposed;
- TypeMask use(Element local) {
+ T use(Element local) {
if (capturedAndBoxed.containsKey(local)) {
- return inferrer.getTypeOfElement(capturedAndBoxed[local]);
+ return types.getTypeOfCapturedAndBoxedVariable(capturedAndBoxed[local]);
}
return locals[local];
}
- void update(Element local, TypeMask type) {
+ void update(Element local, T type) {
assert(type != null);
if (compiler.trustTypeAnnotations || compiler.enableTypeAssertions) {
- type = narrowType(type, local.computeType(compiler), compiler);
+ type = types.narrowType(type, local.computeType(compiler));
}
if (capturedAndBoxed.containsKey(local) || inTryBlock) {
// If a local is captured and boxed, or is set in a try block,
@@ -178,7 +244,7 @@
// We don't know if an assignment in a try block
// will be executed, so all assigments in that block are
// potential types after we have left it.
- type = computeLUB(locals[local], type, compiler);
+ type = types.computeLUB(locals[local], type);
}
locals[local] = type;
}
@@ -191,16 +257,16 @@
* Merge handlers [first] and [second] into [:this:] and returns
* whether the merge changed one of the variables types in [first].
*/
- bool merge(LocalsHandler other, {bool discardIfAborts: true}) {
- VariableScope currentOther = other.locals;
+ bool merge(LocalsHandler<T> other, {bool discardIfAborts: true}) {
+ VariableScope<T> currentOther = other.locals;
assert(currentOther != locals);
bool changed = false;
// Iterate over all updates in the other handler until we reach
// the block level of this handler. We know that [VariableScope]s
// that are lower in block level, are the same.
do {
- currentOther.forEachOwnLocal((Element local, TypeMask otherType) {
- TypeMask myType = locals[local];
+ currentOther.forEachOwnLocal((Element local, T otherType) {
+ T myType = locals[local];
if (myType == null) return;
bool isCaptured = capturedAndBoxed.containsKey(local);
if (!isCaptured && aborts && discardIfAborts) {
@@ -208,7 +274,7 @@
} else if (!isCaptured && other.aborts && discardIfAborts) {
// Don't do anything.
} else {
- TypeMask type = computeLUB(myType, otherType, compiler);
+ T type = types.computeLUB(myType, otherType);
if (type != myType) {
changed = true;
}
@@ -256,13 +322,13 @@
// contain different fields, but if this map does not contain it,
// then we know the field can be null and we don't need to track
// it.
- fieldsInitializedInConstructor.forEach((Element element, TypeMask type) {
- TypeMask otherType = other.fieldsInitializedInConstructor[element];
+ fieldsInitializedInConstructor.forEach((Element element, T type) {
+ T otherType = other.fieldsInitializedInConstructor[element];
if (otherType == null) {
toRemove.add(element);
} else {
fieldsInitializedInConstructor[element] =
- computeLUB(type, otherType, compiler);
+ types.computeLUB(type, otherType);
}
});
// Remove fields that were not initialized in [other].
@@ -276,23 +342,23 @@
return changed;
}
- void updateField(Element element, TypeMask type) {
+ void updateField(Element element, T type) {
if (isThisExposed) return;
fieldsInitializedInConstructor[element] = type;
}
}
-abstract class InferrerVisitor extends ResolvedVisitor<TypeMask> {
+abstract class InferrerVisitor<T> extends ResolvedVisitor<T> {
final Element analyzedElement;
// Subclasses know more about this field. Typing it dynamic to avoid
// warnings.
- final /* TypesInferrer */ inferrer;
+ final TypeSystem<T> types;
final Compiler compiler;
- final Map<TargetElement, List<LocalsHandler>> breaksFor =
- new Map<TargetElement, List<LocalsHandler>>();
+ final Map<TargetElement, List<LocalsHandler<T>>> breaksFor =
+ new Map<TargetElement, List<LocalsHandler<T>>>();
final Map<TargetElement, List<LocalsHandler>> continuesFor =
- new Map<TargetElement, List<LocalsHandler>>();
- LocalsHandler locals;
+ new Map<TargetElement, List<LocalsHandler<T>>>();
+ LocalsHandler<T> locals;
bool accumulateIsChecks = false;
bool conditionIsSimple = false;
@@ -304,108 +370,103 @@
void set isThisExposed(value) { locals.isThisExposed = value; }
InferrerVisitor(Element analyzedElement,
- this.inferrer,
+ this.types,
Compiler compiler,
- [LocalsHandler handler])
+ [LocalsHandler<T> handler])
: this.compiler = compiler,
this.analyzedElement = analyzedElement,
super(compiler.enqueuer.resolution.getCachedElements(analyzedElement)) {
locals = (handler == null)
- ? new LocalsHandler(inferrer, compiler)
+ ? new LocalsHandler<T>(types, compiler)
: handler;
}
- TypeMask visitSendSet(SendSet node);
+ T visitSendSet(SendSet node);
- TypeMask visitSuperSend(Send node);
+ T visitSuperSend(Send node);
- TypeMask visitStaticSend(Send node);
+ T visitStaticSend(Send node);
- TypeMask visitGetterSend(Send node);
+ T visitGetterSend(Send node);
- TypeMask visitClosureSend(Send node);
+ T visitClosureSend(Send node);
- TypeMask visitDynamicSend(Send node);
+ T visitDynamicSend(Send node);
- TypeMask visitForIn(ForIn node);
+ T visitForIn(ForIn node);
- TypeMask visitReturn(Return node);
+ T visitReturn(Return node);
- TypeMask visitNode(Node node) {
+ T visitNode(Node node) {
node.visitChildren(this);
- return compiler.typesTask.dynamicType;
}
- TypeMask visitNewExpression(NewExpression node) {
+ T visitNewExpression(NewExpression node) {
return node.send.accept(this);
}
- TypeMask visit(Node node) {
- return node == null ? compiler.typesTask.dynamicType : node.accept(this);
+ T visit(Node node) {
+ return node == null ? null : node.accept(this);
}
- TypeMask visitFunctionExpression(FunctionExpression node) {
+ T visitFunctionExpression(FunctionExpression node) {
node.visitChildren(this);
- return compiler.typesTask.functionType;
+ return types.functionType;
}
- TypeMask visitFunctionDeclaration(FunctionDeclaration node) {
- locals.update(elements[node], compiler.typesTask.functionType);
+ T visitFunctionDeclaration(FunctionDeclaration node) {
+ locals.update(elements[node], types.functionType);
return visit(node.function);
}
- TypeMask visitLiteralString(LiteralString node) {
- return compiler.typesTask.stringType;
+ T visitLiteralString(LiteralString node) {
+ return types.stringType;
}
- TypeMask visitStringInterpolation(StringInterpolation node) {
+ T visitStringInterpolation(StringInterpolation node) {
node.visitChildren(this);
- return compiler.typesTask.stringType;
+ return types.stringType;
}
- TypeMask visitStringJuxtaposition(StringJuxtaposition node) {
+ T visitStringJuxtaposition(StringJuxtaposition node) {
node.visitChildren(this);
- return compiler.typesTask.stringType;
+ return types.stringType;
}
- TypeMask visitLiteralBool(LiteralBool node) {
- return compiler.typesTask.boolType;
+ T visitLiteralBool(LiteralBool node) {
+ return types.boolType;
}
- TypeMask visitLiteralDouble(LiteralDouble node) {
- return compiler.typesTask.doubleType;
+ T visitLiteralDouble(LiteralDouble node) {
+ return types.doubleType;
}
- TypeMask visitLiteralInt(LiteralInt node) {
+ T visitLiteralInt(LiteralInt node) {
ConstantSystem constantSystem = compiler.backend.constantSystem;
Constant constant = constantSystem.createInt(node.value);
// The JavaScript backend may turn this literal into a double at
// runtime.
return constantSystem.isDouble(constant)
- ? compiler.typesTask.doubleType
- : compiler.typesTask.intType;
+ ? types.doubleType
+ : types.intType;
}
- TypeMask visitLiteralList(LiteralList node) {
+ T visitLiteralList(LiteralList node) {
node.visitChildren(this);
- return node.isConst()
- ? compiler.typesTask.constListType
- : compiler.typesTask.growableListType;
+ return node.isConst() ? types.constListType : types.growableListType;
}
- TypeMask visitLiteralMap(LiteralMap node) {
+ T visitLiteralMap(LiteralMap node) {
node.visitChildren(this);
- return node.isConst()
- ? compiler.typesTask.constMapType
- : compiler.typesTask.mapType;
+ return node.isConst() ? types.constMapType : types.mapType;
}
- TypeMask visitLiteralNull(LiteralNull node) {
- return compiler.typesTask.nullType;
+ T visitLiteralNull(LiteralNull node) {
+ return types.nullType;
}
- TypeMask visitTypeReferenceSend(Send node) {
- return compiler.typesTask.typeType;
+ T visitTypeReferenceSend(Send node) {
+ return types.typeType;
}
bool isThisOrSuper(Node node) => node.isThis() || node.isSuper();
@@ -415,33 +476,32 @@
analyzedElement.getOutermostEnclosingMemberOrTopLevel().implementation;
}
- TypeMask _thisType;
- TypeMask get thisType {
+ T _thisType;
+ T get thisType {
if (_thisType != null) return _thisType;
ClassElement cls = outermostElement.getEnclosingClass();
if (compiler.world.isUsedAsMixin(cls)) {
- return _thisType = new TypeMask.nonNullSubtype(cls.rawType);
+ return _thisType = types.nonNullSubtype(cls.rawType);
} else if (compiler.world.hasAnySubclass(cls)) {
- return _thisType = new TypeMask.nonNullSubclass(cls.rawType);
+ return _thisType = types.nonNullSubclass(cls.rawType);
} else {
- return _thisType = new TypeMask.nonNullExact(cls.rawType);
+ return _thisType = types.nonNullExact(cls.rawType);
}
}
- TypeMask _superType;
- TypeMask get superType {
+ T _superType;
+ T get superType {
if (_superType != null) return _superType;
- return _superType = new TypeMask.nonNullExact(
+ return _superType = types.nonNullExact(
outermostElement.getEnclosingClass().superclass.rawType);
}
- TypeMask visitIdentifier(Identifier node) {
+ T visitIdentifier(Identifier node) {
if (node.isThis()) {
return thisType;
} else if (node.isSuper()) {
return superType;
}
- return compiler.typesTask.dynamicType;
}
void potentiallyAddIsCheck(Send node) {
@@ -460,14 +520,13 @@
}
DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
Element element = elements[node.receiver];
- TypeMask existing = locals.use(element);
- TypeMask newType = narrowType(
- existing, type, compiler, isNullable: false);
+ T existing = locals.use(element);
+ T newType = types.narrowType(existing, type, isNullable: false);
locals.update(element, newType);
}
}
- TypeMask visitOperatorSend(Send node) {
+ T visitOperatorSend(Send node) {
Operator op = node.selector;
if (const SourceString("[]") == op.source) {
return visitDynamicSend(node);
@@ -479,18 +538,18 @@
visit(node.receiver);
accumulateIsChecks = oldAccumulateIsChecks;
if (!accumulateIsChecks) isChecks = null;
- LocalsHandler saved = locals;
- locals = new LocalsHandler.from(locals);
+ LocalsHandler<T> saved = locals;
+ locals = new LocalsHandler<T>.from(locals);
updateIsChecks(isChecks, usePositive: true);
visit(node.arguments.head);
saved.merge(locals);
locals = saved;
- return compiler.typesTask.boolType;
+ return types.boolType;
} else if (const SourceString("||") == op.source) {
conditionIsSimple = false;
visit(node.receiver);
- LocalsHandler saved = locals;
- locals = new LocalsHandler.from(locals);
+ LocalsHandler<T> saved = locals;
+ locals = new LocalsHandler<T>.from(locals);
updateIsChecks(isChecks, usePositive: false);
bool oldAccumulateIsChecks = accumulateIsChecks;
accumulateIsChecks = false;
@@ -498,28 +557,28 @@
accumulateIsChecks = oldAccumulateIsChecks;
saved.merge(locals);
locals = saved;
- return compiler.typesTask.boolType;
+ return types.boolType;
} else if (const SourceString("!") == op.source) {
bool oldAccumulateIsChecks = accumulateIsChecks;
accumulateIsChecks = false;
node.visitChildren(this);
accumulateIsChecks = oldAccumulateIsChecks;
- return compiler.typesTask.boolType;
+ return types.boolType;
} else if (const SourceString("is") == op.source) {
potentiallyAddIsCheck(node);
node.visitChildren(this);
- return compiler.typesTask.boolType;
+ return types.boolType;
} else if (const SourceString("as") == op.source) {
- TypeMask receiverType = visit(node.receiver);
+ T receiverType = visit(node.receiver);
DartType type = elements.getType(node.arguments.head);
- return narrowType(receiverType, type, compiler);
+ return types.narrowType(receiverType, type);
} else if (node.argumentsNode is Prefix) {
// Unary operator.
return visitDynamicSend(node);
} else if (const SourceString('===') == op.source
|| const SourceString('!==') == op.source) {
node.visitChildren(this);
- return compiler.typesTask.boolType;
+ return types.boolType;
} else {
// Binary operator.
return visitDynamicSend(node);
@@ -532,35 +591,34 @@
// to avoid confusing the [ResolvedVisitor].
visitTypeAnnotation(TypeAnnotation node) {}
- TypeMask visitConditional(Conditional node) {
+ T visitConditional(Conditional node) {
List<Send> tests = <Send>[];
bool simpleCondition = handleCondition(node.condition, tests);
- LocalsHandler saved = locals;
- locals = new LocalsHandler.from(locals);
+ LocalsHandler<T> saved = locals;
+ locals = new LocalsHandler<T>.from(locals);
updateIsChecks(tests, usePositive: true);
- TypeMask firstType = visit(node.thenExpression);
- LocalsHandler thenLocals = locals;
+ T firstType = visit(node.thenExpression);
+ LocalsHandler<T> thenLocals = locals;
locals = saved;
if (simpleCondition) updateIsChecks(tests, usePositive: false);
- TypeMask secondType = visit(node.elseExpression);
+ T secondType = visit(node.elseExpression);
locals.merge(thenLocals);
- TypeMask type = computeLUB(firstType, secondType, compiler);
+ T type = types.computeLUB(firstType, secondType);
return type;
}
- TypeMask visitVariableDefinitions(VariableDefinitions node) {
+ T visitVariableDefinitions(VariableDefinitions node) {
for (Link<Node> link = node.definitions.nodes;
!link.isEmpty;
link = link.tail) {
Node definition = link.head;
if (definition is Identifier) {
- locals.update(elements[definition], compiler.typesTask.nullType);
+ locals.update(elements[definition], types.nullType);
} else {
assert(definition.asSendSet() != null);
visit(definition);
}
}
- return compiler.typesTask.dynamicType;
}
bool handleCondition(Node node, List<Send> tests) {
@@ -578,19 +636,18 @@
return simpleCondition;
}
- TypeMask visitIf(If node) {
+ T visitIf(If node) {
List<Send> tests = <Send>[];
bool simpleCondition = handleCondition(node.condition, tests);
- LocalsHandler saved = locals;
- locals = new LocalsHandler.from(locals);
+ LocalsHandler<T> saved = locals;
+ locals = new LocalsHandler<T>.from(locals);
updateIsChecks(tests, usePositive: true);
visit(node.thenPart);
- LocalsHandler thenLocals = locals;
+ LocalsHandler<T> thenLocals = locals;
locals = saved;
if (simpleCondition) updateIsChecks(tests, usePositive: false);
visit(node.elsePart);
locals.merge(thenLocals);
- return compiler.typesTask.dynamicType;
}
void setupBreaksAndContinues(TargetElement element) {
@@ -607,7 +664,7 @@
void mergeBreaks(TargetElement element) {
if (element == null) return;
if (!element.isBreakTarget) return;
- for (LocalsHandler handler in breaksFor[element]) {
+ for (LocalsHandler<T> handler in breaksFor[element]) {
locals.merge(handler, discardIfAborts: false);
}
}
@@ -616,20 +673,20 @@
if (element == null) return false;
if (!element.isContinueTarget) return false;
bool changed = false;
- for (LocalsHandler handler in continuesFor[element]) {
+ for (LocalsHandler<T> handler in continuesFor[element]) {
changed = locals.merge(handler, discardIfAborts: false) || changed;
}
return changed;
}
- TypeMask handleLoop(Node node, void logic()) {
+ T handleLoop(Node node, void logic()) {
loopLevel++;
bool changed = false;
TargetElement target = elements[node];
setupBreaksAndContinues(target);
do {
- LocalsHandler saved = locals;
- locals = new LocalsHandler.from(locals);
+ LocalsHandler<T> saved = locals;
+ locals = new LocalsHandler<T>.from(locals);
logic();
changed = saved.merge(locals);
locals = saved;
@@ -638,10 +695,9 @@
loopLevel--;
mergeBreaks(target);
clearBreaksAndContinues(target);
- return compiler.typesTask.dynamicType;
}
- TypeMask visitWhile(While node) {
+ T visitWhile(While node) {
return handleLoop(node, () {
List<Send> tests = <Send>[];
handleCondition(node.condition, tests);
@@ -650,7 +706,7 @@
});
}
- TypeMask visitDoWhile(DoWhile node) {
+ T visitDoWhile(DoWhile node) {
return handleLoop(node, () {
visit(node.body);
List<Send> tests = <Send>[];
@@ -659,7 +715,7 @@
});
}
- TypeMask visitFor(For node) {
+ T visitFor(For node) {
visit(node.initializer);
return handleLoop(node, () {
List<Send> tests = <Send>[];
@@ -670,101 +726,94 @@
});
}
- TypeMask visitTryStatement(TryStatement node) {
- LocalsHandler saved = locals;
- locals = new LocalsHandler.from(locals, inTryBlock: true);
+ T visitTryStatement(TryStatement node) {
+ LocalsHandler<T> saved = locals;
+ locals = new LocalsHandler<T>.from(locals, inTryBlock: true);
visit(node.tryBlock);
saved.merge(locals);
locals = saved;
for (Node catchBlock in node.catchBlocks) {
saved = locals;
- locals = new LocalsHandler.from(locals);
+ locals = new LocalsHandler<T>.from(locals);
visit(catchBlock);
saved.merge(locals);
locals = saved;
}
visit(node.finallyBlock);
- return compiler.typesTask.dynamicType;
}
- TypeMask visitThrow(Throw node) {
+ T visitThrow(Throw node) {
node.visitChildren(this);
locals.seenReturnOrThrow = true;
- return compiler.typesTask.dynamicType;
+ return types.dynamicType;
}
- TypeMask visitCatchBlock(CatchBlock node) {
+ T visitCatchBlock(CatchBlock node) {
Node exception = node.exception;
if (exception != null) {
DartType type = elements.getType(node.type);
- TypeMask mask = type == null
- ? compiler.typesTask.dynamicType
- : new TypeMask.nonNullSubtype(type.asRaw());
+ T mask = type == null
+ ? types.dynamicType
+ : types.nonNullSubtype(type.asRaw());
locals.update(elements[exception], mask);
}
Node trace = node.trace;
if (trace != null) {
- locals.update(elements[trace], compiler.typesTask.dynamicType);
+ locals.update(elements[trace], types.dynamicType);
}
visit(node.block);
- return compiler.typesTask.dynamicType;
}
- TypeMask visitParenthesizedExpression(ParenthesizedExpression node) {
+ T visitParenthesizedExpression(ParenthesizedExpression node) {
return visit(node.expression);
}
- TypeMask visitBlock(Block node) {
+ T visitBlock(Block node) {
if (node.statements != null) {
for (Node statement in node.statements) {
visit(statement);
if (locals.aborts) break;
}
}
- return compiler.typesTask.dynamicType;
}
- TypeMask visitLabeledStatement(LabeledStatement node) {
+ T visitLabeledStatement(LabeledStatement node) {
Statement body = node.statement;
if (body is Loop
|| body is SwitchStatement
|| Elements.isUnusedLabel(node, elements)) {
// Loops and switches handle their own labels.
visit(body);
- return compiler.typesTask.dynamicType;
+ } else {
+ TargetElement targetElement = elements[body];
+ setupBreaksAndContinues(targetElement);
+ visit(body);
+ mergeBreaks(targetElement);
+ clearBreaksAndContinues(targetElement);
}
-
- TargetElement targetElement = elements[body];
- setupBreaksAndContinues(targetElement);
- visit(body);
- mergeBreaks(targetElement);
- clearBreaksAndContinues(targetElement);
- return compiler.typesTask.dynamicType;
}
- TypeMask visitBreakStatement(BreakStatement node) {
+ T visitBreakStatement(BreakStatement node) {
TargetElement target = elements[node];
locals.seenBreakOrContinue = true;
// Do a deep-copy of the locals, because the code following the
// break will change them.
- breaksFor[target].add(new LocalsHandler.deepCopyOf(locals));
- return compiler.typesTask.dynamicType;
+ breaksFor[target].add(new LocalsHandler<T>.deepCopyOf(locals));
}
- TypeMask visitContinueStatement(ContinueStatement node) {
+ T visitContinueStatement(ContinueStatement node) {
TargetElement target = elements[node];
locals.seenBreakOrContinue = true;
// Do a deep-copy of the locals, because the code following the
// continue will change them.
- continuesFor[target].add(new LocalsHandler.deepCopyOf(locals));
- return compiler.typesTask.dynamicType;
+ continuesFor[target].add(new LocalsHandler<T>.deepCopyOf(locals));
}
void internalError(String reason, {Node node}) {
compiler.internalError(reason, node: node);
}
- TypeMask visitSwitchStatement(SwitchStatement node) {
+ T visitSwitchStatement(SwitchStatement node) {
visit(node.parenthesizedExpression);
setupBreaksAndContinues(elements[node]);
@@ -792,8 +841,8 @@
do {
changed = false;
for (Node switchCase in node.cases) {
- LocalsHandler saved = locals;
- locals = new LocalsHandler.from(locals);
+ LocalsHandler<T> saved = locals;
+ locals = new LocalsHandler<T>.from(locals);
visit(switchCase);
changed = saved.merge(locals, discardIfAborts: false) || changed;
locals = saved;
@@ -804,8 +853,8 @@
clearBreaksAndContinues(target);
});
} else {
- LocalsHandler saved = locals;
- List<LocalsHandler> localsToMerge = <LocalsHandler>[];
+ LocalsHandler<T> saved = locals;
+ List<LocalsHandler<T>> localsToMerge = <LocalsHandler>[];
for (SwitchCase switchCase in node.cases) {
if (switchCase.isDefaultCase) {
@@ -815,12 +864,12 @@
locals = saved;
visit(switchCase);
} else {
- locals = new LocalsHandler.from(saved);
+ locals = new LocalsHandler<T>.from(saved);
visit(switchCase);
localsToMerge.add(locals);
}
}
- for (LocalsHandler handler in localsToMerge) {
+ for (LocalsHandler<T> handler in localsToMerge) {
saved.merge(handler, discardIfAborts: false);
}
locals = saved;
@@ -835,6 +884,17 @@
// that the [visitBlock] method does not assume the code after the
// switch is dead code.
locals.seenBreakOrContinue = false;
- return compiler.typesTask.dynamicType;
+ }
+
+ T visitCascadeReceiver(CascadeReceiver node) {
+ // TODO(ngeoffray): Implement.
+ node.visitChildren(this);
+ return types.dynamicType;
+ }
+
+ T visitCascade(Cascade node) {
+ // TODO(ngeoffray): Implement.
+ node.visitChildren(this);
+ return types.dynamicType;
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index 2a0c230..df69132 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -172,11 +172,14 @@
class SimpleTypesInferrer extends TypesInferrer {
InternalSimpleTypesInferrer internal;
- Compiler compiler;
+ final Compiler compiler;
+ final TypeMaskSystem types;
SimpleTypesInferrer(Compiler compiler) :
compiler = compiler,
- internal = new InternalSimpleTypesInferrer(compiler, OPTIMISTIC);
+ types = new TypeMaskSystem(compiler) {
+ internal = new InternalSimpleTypesInferrer(this, OPTIMISTIC);
+ }
TypeMask getReturnTypeOfElement(Element element) {
if (compiler.disableTypeInference) return compiler.typesTask.dynamicType;
@@ -206,7 +209,7 @@
assert(internal.optimismState == RETRY);
// Discard the inferrer and start again with a pessimistic one.
- internal = new InternalSimpleTypesInferrer(compiler, PESSIMISTIC);
+ internal = new InternalSimpleTypesInferrer(this, PESSIMISTIC);
return internal.analyzeMain(element);
}
@@ -264,22 +267,7 @@
int optimismState;
- bool isDynamicType(TypeMask type) => identical(type, dynamicType);
- TypeMask get dynamicType => compiler.typesTask.dynamicType;
- TypeMask get nullType => compiler.typesTask.nullType;
- TypeMask get intType => compiler.typesTask.intType;
- TypeMask get doubleType => compiler.typesTask.doubleType;
- TypeMask get numType => compiler.typesTask.numType;
- TypeMask get boolType => compiler.typesTask.boolType;
- TypeMask get functionType => compiler.typesTask.functionType;
- TypeMask get listType => compiler.typesTask.listType;
- TypeMask get constListType => compiler.typesTask.constListType;
- TypeMask get fixedListType => compiler.typesTask.fixedListType;
- TypeMask get growableListType => compiler.typesTask.growableListType;
- TypeMask get mapType => compiler.typesTask.mapType;
- TypeMask get constMapType => compiler.typesTask.constMapType;
- TypeMask get stringType => compiler.typesTask.stringType;
- TypeMask get typeType => compiler.typesTask.typeType;
+ bool isDynamicType(TypeMask type) => identical(type, types.dynamicType);
/**
* These are methods that are expected to return only bool. We optimistically
@@ -328,7 +316,11 @@
*/
int analyzed = 0;
- InternalSimpleTypesInferrer(this.compiler, this.optimismState);
+ final TypeMaskSystem types;
+
+ InternalSimpleTypesInferrer(SimpleTypesInferrer inferrer, this.optimismState)
+ : this.compiler = inferrer.compiler,
+ this.types = inferrer.types;
/**
* Main entry point of the inferrer. Analyzes all elements that the resolver
@@ -406,7 +398,7 @@
}
TypeMask getNonNullType(TypeMask returnType) {
- return returnType != null ? returnType : dynamicType;
+ return returnType != null ? returnType : types.dynamicType;
}
Iterable<Element> getCallersOf(Element element) {
@@ -490,7 +482,7 @@
if (optimismState == OPTIMISTIC) {
FunctionTypeInformation info =
typeInformationOf(element.implementation);
- info.returnType = boolType;
+ info.returnType = types.boolType;
}
} else {
// Put the other operators in buckets by length, later to be added in
@@ -544,11 +536,11 @@
typeInfo.forEach((element, TypeInformation info) {
TypeMask type = info.type;
TypeMask returnType = info.returnType;
- if (type != null && type != nullType && !isDynamicType(type)) {
+ if (type != null && type != types.nullType && !isDynamicType(type)) {
interestingTypes++;
}
if (returnType != null
- && returnType != nullType
+ && returnType != types.nullType
&& !isDynamicType(returnType)) {
interestingTypes++;
}
@@ -617,7 +609,7 @@
// If the type is useful, say it has changed.
return existing != newType
&& !isDynamicType(newType)
- && newType != nullType;
+ && newType != types.nullType;
}
/**
@@ -642,7 +634,7 @@
// If the return type is useful, say it has changed.
return existing != newType
&& !isDynamicType(newType)
- && newType != nullType;
+ && newType != types.nullType;
}
bool isNativeElement(Element element) {
@@ -667,19 +659,19 @@
assert(annotation is FunctionType);
annotation = annotation.returnType;
}
- newType = narrowType(newType, annotation, compiler);
+ newType = types.narrowType(newType, annotation);
}
return newType;
}
TypeMask fetchReturnType(Element element) {
TypeMask returnType = typeInformationOf(element).returnType;
- return returnType is ElementTypeMask ? dynamicType : returnType;
+ return returnType is ElementTypeMask ? types.dynamicType : returnType;
}
TypeMask fetchType(Element element) {
TypeMask type = typeInformationOf(element).type;
- return type is ElementTypeMask ? dynamicType : type;
+ return type is ElementTypeMask ? types.dynamicType : type;
}
/**
@@ -698,7 +690,7 @@
if (info.returnType == null) {
var elementType = element.computeType(compiler);
if (elementType.kind != TypeKind.FUNCTION) {
- info.returnType = dynamicType;
+ info.returnType = types.dynamicType;
} else {
info.returnType = typeOfNativeBehavior(
native.NativeBehavior.ofMethod(element, compiler));
@@ -713,7 +705,8 @@
|| element.isGetter()
|| element.isFactoryConstructor())) {
FunctionType functionType = element.computeType(compiler);
- returnType = narrowType(dynamicType, functionType.returnType, compiler);
+ returnType = types.narrowType(
+ types.dynamicType, functionType.returnType);
} else {
returnType = info.returnType =
new ElementTypeMask(fetchReturnType, element);
@@ -723,30 +716,30 @@
}
TypeMask typeOfNativeBehavior(native.NativeBehavior nativeBehavior) {
- if (nativeBehavior == null) return dynamicType;
+ if (nativeBehavior == null) return types.dynamicType;
List typesReturned = nativeBehavior.typesReturned;
- if (typesReturned.isEmpty) return dynamicType;
+ if (typesReturned.isEmpty) return types.dynamicType;
TypeMask returnType;
for (var type in typesReturned) {
TypeMask mappedType;
if (type == native.SpecialType.JsObject) {
mappedType = new TypeMask.nonNullExact(rawTypeOf(compiler.objectClass));
} else if (type.element == compiler.stringClass) {
- mappedType = stringType;
+ mappedType = types.stringType;
} else if (type.element == compiler.intClass) {
- mappedType = intType;
+ mappedType = types.intType;
} else if (type.element == compiler.doubleClass) {
- mappedType = doubleType;
+ mappedType = types.doubleType;
} else if (type.element == compiler.numClass) {
- mappedType = numType;
+ mappedType = types.numType;
} else if (type.element == compiler.boolClass) {
- mappedType = boolType;
+ mappedType = types.boolType;
} else if (type.element == compiler.nullClass) {
- mappedType = nullType;
+ mappedType = types.nullType;
} else if (type.isVoid) {
- mappedType = nullType;
+ mappedType = types.nullType;
} else if (type.isDynamic) {
- return dynamicType;
+ return types.dynamicType;
} else if (!compiler.world.hasAnySubtype(type.element)) {
mappedType = new TypeMask.nonNullExact(rawTypeOf(type.element));
} else {
@@ -759,9 +752,9 @@
mappedType = new TypeMask.nonNullSubtype(rawTypeOf(element));
}
}
- returnType = computeLUB(returnType, mappedType, compiler);
+ returnType = types.computeLUB(returnType, mappedType);
if (!isTypeValuable(returnType)) {
- returnType = dynamicType;
+ returnType = types.dynamicType;
break;
}
}
@@ -781,7 +774,7 @@
if (type == null) {
InterfaceType rawType = element.computeType(compiler).asRaw();
info.type = type = rawType.isDynamic
- ? dynamicType
+ ? types.dynamicType
: new TypeMask.subtype(rawType);
}
assert(type != null);
@@ -796,7 +789,8 @@
// therefore only trust their type after the checks.
|| (compiler.enableTypeAssertions
&& (element.isField() || element.isVariable()))) {
- type = narrowType(dynamicType, element.computeType(compiler), compiler);
+ type = types.narrowType(
+ types.dynamicType, element.computeType(compiler));
} else {
type = info.type = new ElementTypeMask(fetchType, element);
}
@@ -811,14 +805,14 @@
TypeMask typeOfSelector(Selector selector) {
// Bailout for closure calls. We're not tracking types of
// closures.
- if (selector.isClosureCall()) return dynamicType;
- if (selector.isSetter() || selector.isIndexSet()) return dynamicType;
+ if (selector.isClosureCall()) return types.dynamicType;
+ if (selector.isSetter() || selector.isIndexSet()) return types.dynamicType;
TypeMask result;
iterateOverElements(selector, (Element element) {
assert(element.isImplementation);
TypeMask type = typeOfElementWithSelector(element, selector);
- result = computeLUB(result, type, compiler);
+ result = types.computeLUB(result, type);
return isTypeValuable(result);
});
if (result == null) {
@@ -836,11 +830,13 @@
} else if (selector.isGetter()) {
if (element.isFunction()) {
// [functionType] is null if the inferrer did not run.
- return functionType == null ? dynamicType : functionType;
+ return types.functionType == null
+ ? types.dynamicType
+ : types.functionType;
} else if (element.isField()) {
return typeOfElement(element);
} else if (Elements.isUnresolved(element)) {
- return dynamicType;
+ return types.dynamicType;
} else {
assert(element.isGetter());
return returnTypeOfElement(element);
@@ -850,10 +846,10 @@
&& selector.mask.isContainer) {
ContainerTypeMask mask = selector.mask;
TypeMask elementType = mask.elementType;
- return elementType == null ? dynamicType : elementType;
+ return elementType == null ? types.dynamicType : elementType;
} else if (element.isGetter() || element.isField()) {
assert(selector.isCall() || selector.isSetter());
- return dynamicType;
+ return types.dynamicType;
} else {
return returnTypeOfElement(element);
}
@@ -928,7 +924,7 @@
elementType = computeLubFor(elementType, mask, parameter);
});
if (elementType == null) {
- elementType = dynamicType;
+ elementType = types.dynamicType;
}
return recordType(parameter, elementType);
}
@@ -1075,11 +1071,12 @@
return firstType;
}
}
- return computeLUB(firstType, secondType, compiler);
+ return types.computeLUB(firstType, secondType);
}
TypeMask handleIntrisifiedSelector(Selector selector,
ArgumentsTypes arguments) {
+ TypeMask intType = types.intType;
if (selector.mask != intType) return null;
if (!selector.isCall() && !selector.isOperator()) return null;
if (!arguments.named.isEmpty) return null;
@@ -1132,13 +1129,13 @@
if (!selector.isSetter()) {
TypeMask type = handleIntrisifiedSelector(selector, arguments);
if (type == null) type = typeOfElementWithSelector(element, selector);
- result = computeLUB(result, type, compiler);
+ result = types.computeLUB(result, type);
}
}
}
if (result == null) {
- result = dynamicType;
+ result = types.dynamicType;
}
return result;
}
@@ -1177,10 +1174,10 @@
}
TypeMask computeTypeWithConstraints(Element element,
- Map<Node, TypeMask> types) {
+ Map<Node, TypeMask> assignments) {
List<CallSite> constraints = <CallSite>[];
TypeMask elementType;
- types.forEach((Node node, TypeMask mask) {
+ assignments.forEach((Node node, TypeMask mask) {
CallSite constraint = setterConstraints[node];
if (constraint != null) {
// If this update has a constraint, we collect it and don't
@@ -1216,7 +1213,7 @@
assert(selector.isGetter());
type = typeOfSelector(selector);
}
- elementType = computeLUB(elementType, type, compiler);
+ elementType = types.computeLUB(elementType, type);
}
info.type = existing;
}
@@ -1343,19 +1340,21 @@
}
}
-class SimpleTypeInferrerVisitor extends InferrerVisitor {
+class SimpleTypeInferrerVisitor extends InferrerVisitor<TypeMask> {
TypeMask returnType;
bool visitingInitializers = false;
bool isConstructorRedirect = false;
SideEffects sideEffects = new SideEffects.empty();
final Element outermostElement;
+ final InternalSimpleTypesInferrer inferrer;
SimpleTypeInferrerVisitor.internal(analyzedElement,
this.outermostElement,
inferrer,
compiler,
locals)
- : super(analyzedElement, inferrer, compiler, locals);
+ : super(analyzedElement, inferrer.types, compiler, locals),
+ this.inferrer = inferrer;
factory SimpleTypeInferrerVisitor(Element element,
Compiler compiler,
@@ -1373,7 +1372,7 @@
if (analyzedElement.isField() && node.asSendSet() == null) {
// Eagerly bailout, because computing the closure data only
// works for functions and field assignments.
- return inferrer.nullType;
+ return types.nullType;
}
// Update the locals that are boxed in [locals]. These locals will
// be handled specially, in that we are computing their LUB at
@@ -1402,14 +1401,14 @@
Send send = node.asSendSet();
ParameterTypeInformation info = inferrer.typeInformationOf(element);
info.defaultType = (send == null)
- ? inferrer.nullType
+ ? types.nullType
: visit(send.arguments.head);
});
if (analyzedElement.isNative()) {
// Native methods do not have a body, and we currently just say
// they return dynamic.
- return inferrer.dynamicType;
+ return types.dynamicType;
}
if (analyzedElement.isGenerativeConstructor()) {
@@ -1455,7 +1454,7 @@
TypeMask type = locals.fieldsInitializedInConstructor[field];
if (type == null && field.parseNode(compiler).asSendSet() == null) {
inferrer.recordNonFinalFieldElementType(
- node, field, inferrer.nullType, null);
+ node, field, types.nullType, null);
}
});
}
@@ -1470,7 +1469,7 @@
// No return in the body.
returnType = locals.seenReturnOrThrow
? new TypeMask.nonNullEmpty() // Body always throws.
- : inferrer.nullType;
+ : types.nullType;
} else if (!locals.seenReturnOrThrow &&
!inferrer.isDynamicType(returnType)) {
// We haven't seen returns on all branches. So the method may
@@ -1484,7 +1483,7 @@
// bool.
signature.forEachParameter((Element parameter) {
if (inferrer.typeOfElement(parameter).isNullable){
- returnType = computeLUB(returnType, inferrer.boolType, compiler);
+ returnType = types.computeLUB(returnType, types.boolType);
}
});
}
@@ -1532,7 +1531,7 @@
inferrer.recordType(field, locals.locals[variable]);
});
- return inferrer.functionType;
+ return types.functionType;
}
TypeMask visitLiteralList(LiteralList node) {
@@ -1541,12 +1540,12 @@
// when re-analyzing the node.
return inferrer.concreteTypes.putIfAbsent(node, () {
ContainerTypeMask container = new ContainerTypeMask(
- inferrer.constListType, node, outermostElement);
+ types.constListType, node, outermostElement);
TypeMask elementType = new TypeMask.nonNullEmpty();
int length = 0;
for (Node element in node.elements.nodes) {
length++;
- elementType = computeLUB(elementType, visit(element), compiler);
+ elementType = types.computeLUB(elementType, visit(element));
}
container.elementType = elementType;
container.length = length;
@@ -1556,7 +1555,7 @@
node.visitChildren(this);
return inferrer.concreteTypes.putIfAbsent(
node, () => new ContainerTypeMask(
- inferrer.growableListType, node, outermostElement));
+ types.growableListType, node, outermostElement));
}
}
@@ -1577,7 +1576,7 @@
// null.
inferrer.recordNonFinalFieldElementType(
analyzedElement.parseNode(compiler), element,
- inferrer.nullType, null);
+ types.nullType, null);
}
// Accessing a field does not expose [:this:].
return true;
@@ -1593,7 +1592,7 @@
Element element = elements[node];
if (!Elements.isUnresolved(element) && element.impliesType()) {
node.visitChildren(this);
- return inferrer.dynamicType;
+ return types.dynamicType;
}
Selector getterSelector =
@@ -1621,7 +1620,7 @@
TypeMask indexType;
if (isIncrementOrDecrement) {
- rhsType = inferrer.intType;
+ rhsType = types.intType;
if (node.isIndex) indexType = visit(node.arguments.head);
} else if (node.isIndex) {
indexType = visit(node.arguments.head);
@@ -1716,7 +1715,7 @@
locals.update(element, newType);
} else {
// Bogus SendSet, for example [: myMethod += 42 :].
- getterType = inferrer.dynamicType;
+ getterType = types.dynamicType;
newType = handleDynamicSend(
node, operatorSelector, getterType, operatorArguments);
}
@@ -1780,7 +1779,7 @@
TypeMask visitSuperSend(Send node) {
Element element = elements[node];
if (Elements.isUnresolved(element)) {
- return inferrer.dynamicType;
+ return types.dynamicType;
}
Selector selector = elements.getSelector(node);
// TODO(ngeoffray): We could do better here if we knew what we
@@ -1790,7 +1789,7 @@
handleStaticSend(node, selector, element, null);
return inferrer.typeOfElementWithSelector(element, selector);
} else if (element.isFunction()) {
- if (!selector.applies(element, compiler)) return inferrer.dynamicType;
+ if (!selector.applies(element, compiler)) return types.dynamicType;
ArgumentsTypes arguments = analyzeArguments(node.arguments);
handleStaticSend(node, selector, element, arguments);
return inferrer.returnTypeOfElement(element);
@@ -1798,7 +1797,7 @@
analyzeArguments(node.arguments);
// Closure call on a getter. We don't have function types yet,
// so we just return [:dynamic:].
- return inferrer.dynamicType;
+ return types.dynamicType;
}
}
@@ -1812,24 +1811,24 @@
}
Selector selector = elements.getSelector(node);
ArgumentsTypes arguments = analyzeArguments(node.arguments);
- if (!selector.applies(element, compiler)) return inferrer.dynamicType;
+ if (!selector.applies(element, compiler)) return types.dynamicType;
handleStaticSend(node, selector, element, arguments);
if (Elements.isGrowableListConstructorCall(element, node, compiler)) {
return inferrer.concreteTypes.putIfAbsent(
node, () => new ContainerTypeMask(
- inferrer.growableListType, node, outermostElement));
+ types.growableListType, node, outermostElement));
} else if (Elements.isFixedListConstructorCall(element, node, compiler)
|| Elements.isFilledListConstructorCall(element, node, compiler)) {
return inferrer.concreteTypes.putIfAbsent(
node, () => new ContainerTypeMask(
- inferrer.fixedListType, node, outermostElement));
+ types.fixedListType, node, outermostElement));
} else if (element.isFunction() || element.isConstructor()) {
return inferrer.returnTypeOfElement(element);
} else {
assert(element.isField() || element.isGetter());
// Closure call.
- return inferrer.dynamicType;
+ return types.dynamicType;
}
}
@@ -1845,10 +1844,10 @@
} else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')
|| name == const SourceString('JS_OPERATOR_AS_PREFIX')
|| name == const SourceString('JS_OBJECT_CLASS_NAME')) {
- return inferrer.stringType;
+ return types.stringType;
} else {
sideEffects.setAllSideEffects();
- return inferrer.dynamicType;
+ return types.dynamicType;
}
}
@@ -1880,15 +1879,15 @@
return visitDynamicSend(node);
} else if (Elements.isStaticOrTopLevelFunction(element)) {
handleStaticSend(node, selector, element, null);
- return inferrer.functionType;
+ return types.functionType;
} else if (Elements.isErroneousElement(element)) {
- return inferrer.dynamicType;
+ return types.dynamicType;
} else if (Elements.isLocal(element)) {
assert(locals.use(element) != null);
return locals.use(element);
} else {
node.visitChildren(this);
- return inferrer.dynamicType;
+ return types.dynamicType;
}
}
@@ -1906,7 +1905,7 @@
}
sideEffects.setDependsOnSomething();
sideEffects.setAllSideEffects();
- return inferrer.dynamicType;
+ return types.dynamicType;
}
void handleStaticSend(Node node,
@@ -1992,7 +1991,7 @@
if (node.isRedirectingFactoryBody) {
Element element = elements[node.expression];
if (Elements.isErroneousElement(element)) {
- recordReturnType(inferrer.dynamicType);
+ recordReturnType(types.dynamicType);
} else {
element = element.implementation;
// We don't create a selector for redirecting factories, and
@@ -2021,11 +2020,10 @@
} else {
Node expression = node.expression;
recordReturnType(expression == null
- ? inferrer.nullType
+ ? types.nullType
: expression.accept(this));
}
locals.seenReturnOrThrow = true;
- return inferrer.dynamicType;
}
TypeMask visitForIn(ForIn node) {
@@ -2059,7 +2057,7 @@
if (element != null && element.isInstanceMember()) {
receiverType = thisType;
} else {
- receiverType = inferrer.dynamicType;
+ receiverType = types.dynamicType;
}
handlePlainAssignment(identifier, element, selector,
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index ee30a60..b7442dd 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -120,6 +120,8 @@
"super call arguments and constructor parameters don't match");
static const NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT = const MessageKind(
"implicit super call arguments and constructor parameters don't match");
+ static const CONST_CALLS_NON_CONST = const MessageKind(
+ "const constructor cannot call a non-const constructor");
static const INITIALIZING_FORMAL_NOT_ALLOWED = const MessageKind(
'an initializing formal parameter is only allowed in '
'non-redirecting generative constructors');
diff --git a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
index aeb24ac..634a76f 100644
--- a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
+++ b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
@@ -30,7 +30,7 @@
: super(server),
_inner = server;
- void close() => _inner.close();
+ Future close() => _inner.close();
int get port => _inner.port;
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 66a769d..fcfc43b 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -4,19 +4,10 @@
part of dart.async;
-class _BroadcastStream<T> extends _StreamImpl<T> {
- _BroadcastStreamController _controller;
-
- _BroadcastStream(this._controller);
+class _BroadcastStream<T> extends _ControllerStream<T> {
+ _BroadcastStream(_StreamControllerLifecycle controller) : super(controller);
bool get isBroadcast => true;
-
- StreamSubscription<T> _createSubscription(
- void onData(T data),
- void onError(Object error),
- void onDone(),
- bool cancelOnError) =>
- _controller._subscribe(onData, onError, onDone, cancelOnError);
}
abstract class _BroadcastSubscriptionLink {
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index e0ba58a..5b3d760 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -602,9 +602,10 @@
int get hashCode => _controller.hashCode ^ 0x35323532;
bool operator==(Object other) {
+ if (identical(this, other)) return true;
if (other is! _ControllerStream) return false;
_ControllerStream otherStream = other;
- return identical(otherStream._controller, this);
+ return identical(otherStream._controller, this._controller);
}
}
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 452dbe7..5d316eb 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -168,10 +168,13 @@
=> new _HttpServer.listenOn(serverSocket);
/**
- * Permanently stops this [HttpServer] from listening for new connections.
- * This closes this [Stream] of [HttpRequest]s with a done event.
+ * Permanently stops this [HttpServer] from listening for new
+ * connections. This closes this [Stream] of [HttpRequest]s with a
+ * done event. The returned future completes when the server is
+ * stopped. For a server started using [bind] or [bindSecure] this
+ * means that the port listened on no longer in use.
*/
- void close();
+ Future close();
/**
* Returns the port that the server is listening on. This can be
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 4931831..98a3cf9 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -1926,10 +1926,13 @@
cancelOnError: cancelOnError);
}
- void close() {
+ Future close() {
closed = true;
+ Future result;
if (_serverSocket != null && _closeServer) {
- _serverSocket.close();
+ result = _serverSocket.close();
+ } else {
+ result = new Future.value();
}
if (_sessionManagerInstance != null) {
_sessionManagerInstance.close();
@@ -1939,6 +1942,7 @@
connection.destroy();
}
_connections.clear();
+ return result;
}
int get port {
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index 957440e..e82adc7 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -257,9 +257,10 @@
int get port;
/**
- * Closes the socket.
+ * Closes the socket. The returned future completes when the socket
+ * is fully closed and is no longer bound.
*/
- void close();
+ Future close();
}
/**
@@ -300,12 +301,14 @@
static const RawSocketEvent READ = const RawSocketEvent._(0);
static const RawSocketEvent WRITE = const RawSocketEvent._(1);
static const RawSocketEvent READ_CLOSED = const RawSocketEvent._(2);
+ static const RawSocketEvent CLOSED = const RawSocketEvent._(3);
const RawSocketEvent._(this._value);
final int _value;
String toString() {
return ['RawSocketEvent:READ',
'RawSocketEvent:WRITE',
- 'RawSocketEvent:READ_CLOSED'][_value];
+ 'RawSocketEvent:READ_CLOSED',
+ 'RawSocketEvent:CLOSED'][_value];
}
}
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 16e1222..932743a 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -172,7 +172,6 @@
Language/07_Classes/6_Constructors/2_Factories_A01_t05: Fail # Inherited from dartjs
Language/07_Classes/6_Constructors/2_Factories_A07_t01: Fail # inherited from VM
Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t01: Fail # http://dartbug.com/5519
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t02: Fail # http://dartbug.com/5519
Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: Fail # inherited from VM
Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: Fail # inherited from VM
Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t03: Fail # inherited from VM
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 33ec9d5..554472b 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -691,7 +691,6 @@
Language/07_Classes/4_Abstract_Instance_Members_A04_t06: Fail # Checks that a compile-time error is produced when the overriding non-abstract instance method has almost the same set of named parameters as the abstract method being overriden, except for one that has a different name.
Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: Fail # Checks that error is produced if a final variable is not initialized in one of the specified ways.
Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t01: Fail # Checks that a compile-time error is produced when a class with constant constructor also declares a non-final instance variable.
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t02: Fail # Checks that compile-time error is produced when a class with constant constructor inherits a non-final instance variable.
Language/07_Classes/6_Constructors_A02_t01: Fail # Checks that a compile-error is produced when a named constructor definition does not begin with the name of its class.
Language/11_Expressions/01_Constants_A16_t01: Fail # Checks that an IntegerDivisionByZeroException raised during evaluation of a compile-time constant causes a compile-time error.
Language/11_Expressions/01_Constants_A16_t02: Fail # Checks that an OutOfMemoryException raised during evaluation of a compile-time constant causes a compile-time error.
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index d6e1a83..abb669a 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -292,6 +292,28 @@
result.checkNodeHasType('bar', [result.int]);
}
+testDoWhile() {
+ final String source = r"""
+ class A { f() => new B(); }
+ class B { f() => new C(); }
+ class C { f() => new A(); }
+ main() {
+ var bar = null;
+ var foo = new A();
+ do {
+ foo = foo.f();
+ } while (bar = 42);
+ foo; bar;
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType(
+ 'foo',
+ [result.base('A'), result.base('B'), result.base('C')]);
+ // Check that the condition is evaluated.
+ result.checkNodeHasType('bar', [result.int]);
+}
+
testFor1() {
final String source = r"""
class A { f() => new B(); }
@@ -887,6 +909,21 @@
}
}
+testBooleanOperatorsShortCirtcuit() {
+ String source(op) {
+ return """
+ main() {
+ var x = null;
+ "foo" $op (x = 42);
+ x;
+ }""";
+ }
+ for (String op in ['&&', '||']) {
+ AnalysisResult result = analyze(source(op));
+ result.checkNodeHasType('x', [result.nullType, result.int]);
+ }
+}
+
testOperators() {
final String source = r"""
class A {
@@ -1071,21 +1108,43 @@
testLists() {
final String source = r"""
+ class A {}
+ class B {}
+ class C {}
+ class D {}
+ class E {}
+ class F {}
+ class G {}
+
main() {
- var l1 = [1.2];
+ var l1 = [new A()];
var l2 = [];
- l1['a'] = 42; // raises an error, so int should not be recorded
- l1[1] = 'abc';
- "__dynamic_for_test"[1] = true;
- var x = l1[1];
- var y = l2[1];
- var z = l1['foo'];
- x; y; z;
+ l1['a'] = new B(); // raises an error, so B should not be recorded
+ l1[1] = new C();
+ l1.add(new D());
+ l1.insert('a', new E()); // raises an error, so E should not be recorded
+ l1.insert(1, new F());
+ "__dynamic_for_test"[1] = new G();
+ var x1 = l1[1];
+ var x2 = l2[1];
+ var x3 = l1['foo']; // raises an error, should return empty
+ var x4 = l1.removeAt(1);
+ var x5 = l2.removeAt(1);
+ var x6 = l1.removeAt('a'); // raises an error, should return empty
+ var x7 = l1.removeLast();
+ var x8 = l2.removeLast();
+ x1; x2; x3; x4; x5; x6; x7; x8;
}""";
AnalysisResult result = analyze(source);
- result.checkNodeHasType('x', [result.double, result.string, result.bool]);
- result.checkNodeHasType('y', [result.double, result.string, result.bool]);
- result.checkNodeHasType('z', []);
+ final expectedTypes = ['A', 'C', 'D', 'F', 'G'].map(result.base).toList();
+ result.checkNodeHasType('x1', expectedTypes);
+ result.checkNodeHasType('x2', expectedTypes);
+ result.checkNodeHasType('x3', []);
+ result.checkNodeHasType('x4', expectedTypes);
+ result.checkNodeHasType('x5', expectedTypes);
+ result.checkNodeHasType('x6', []);
+ result.checkNodeHasType('x7', expectedTypes);
+ result.checkNodeHasType('x8', expectedTypes);
}
testListWithCapacity() {
@@ -1529,6 +1588,7 @@
testIfThenElse();
testTernaryIf();
testWhile();
+ testDoWhile();
testFor1();
testFor2();
testFor3();
@@ -1553,6 +1613,7 @@
// testNoReturn(); // right now we infer the empty type instead of null
testArithmeticOperators();
testBooleanOperators();
+ testBooleanOperatorsShortCirtcuit();
testOperators();
testCompoundOperators1();
testCompoundOperators2();
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index cf84f928..750dc2e 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -107,7 +107,10 @@
var length;
operator[](index) => this[index];
operator[]=(index, value) {}
- var add;
+ add(value) {}
+ removeAt(index) {}
+ insert(index, value) {}
+ removeLast() {}
}
class JSMutableArray extends JSArray implements JSMutableIndexable {}
class JSFixedArray extends JSMutableArray {}
@@ -177,7 +180,7 @@
class bool {}
class String implements Pattern {}
class Object {
- Object();
+ const Object();
operator ==(other) { return true; }
get hashCode => throw "Object.hashCode not implemented.";
String toString() { return null; }
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index ab28e12..c260b67 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -123,11 +123,8 @@
mandel_isolate_test: Pass, Fail, Timeout # Issue 7952
mandel_isolate_stream_test: Pass, Fail, Timeout # Issue 7952
-[ $compiler == dart2js && ( $runtime == ff || $runtime == safari ) ]
-isolate_stress_test: Pass, Timeout # http://dartbug.com/10697
-
-[ $compiler == dart2js && ( $runtime == drt || $runtime == chrome ) ]
-isolate_stress_test: Pass, Crash, Timeout # issue 11648
+[ $compiler == dart2js && ( $runtime == ff || $runtime == safari || $runtime == drt || $runtime == chrome ) ]
+isolate_stress_test: Pass, Slow # http://dartbug.com/10697
[ $arch == arm || $arch == simarm ]
*: Skip
diff --git a/tests/isolate/isolate_stress_test.dart b/tests/isolate/isolate_stress_test.dart
index 685ea59..84a3447 100644
--- a/tests/isolate/isolate_stress_test.dart
+++ b/tests/isolate/isolate_stress_test.dart
@@ -7,14 +7,10 @@
// in dart2js).
import 'dart:async';
-import 'dart:html';
import 'dart:isolate';
-// TODO(ahe): Remove dependency on unittest when tests are wrapperless.
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-
-const bool IS_UNITTEST = true;
+// TODO(ahe): Remove this import when we have wrapper-less testing.
+import 'dart:html';
worker() {
port.receive((String uri, SendPort replyTo) {
@@ -24,7 +20,6 @@
}
main() {
- useHtmlConfiguration();
try {
// Create a Worker to confuse broken isolate implementation in dart2js.
new Worker('data:application/javascript,').terminate();
@@ -38,25 +33,14 @@
throw new Exception('Unexpected reply from worker: $reply');
}
if (++isolateCount > 200) {
- if (IS_UNITTEST) {
- doneClosure();
- } else {
- port.close();
- window.postMessage('unittest-suite-done', '*');
- }
+ port.close();
+ window.postMessage('unittest-suite-success', '*');
return;
}
spawnFunction(worker).call('').then(spawnMany);
print('isolateCount = $isolateCount');
}
- if (IS_UNITTEST) {
- test('stress test', () {
- spawnMany('Hello from Worker');
- doneClosure = expectAsync0(() {});
- });
- } else {
- spawnMany('Hello from Worker');
- window.postMessage('unittest-suite-wait-for-done', '*');
- }
+ spawnMany('Hello from Worker');
+ window.postMessage('unittest-suite-wait-for-done', '*');
}
diff --git a/tests/language/const_constructor_mixin2_test.dart b/tests/language/const_constructor_mixin2_test.dart
new file mode 100644
index 0000000..7fc27c6
--- /dev/null
+++ b/tests/language/const_constructor_mixin2_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Mixin {
+ var nonFinalField;
+}
+
+class A {
+ const A(foo);
+}
+
+class B extends A
+ with Mixin /// 01: compile-time error
+ {
+ const B(foo) : super(foo);
+}
+
+main() {
+ var a = const B(42);
+ a.nonFinalField = 54; /// 01: continued
+}
diff --git a/tests/language/const_constructor_mixin3_test.dart b/tests/language/const_constructor_mixin3_test.dart
new file mode 100644
index 0000000..c81b7d3
--- /dev/null
+++ b/tests/language/const_constructor_mixin3_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Mixin {
+}
+
+class A {
+ const A();
+}
+
+class B extends A
+ with Mixin /// 01: compile-time error
+ {
+ const B();
+}
+
+main() {
+ var a = const B();
+}
diff --git a/tests/language/const_constructor_mixin_test.dart b/tests/language/const_constructor_mixin_test.dart
index 832be8c..83ad156 100644
--- a/tests/language/const_constructor_mixin_test.dart
+++ b/tests/language/const_constructor_mixin_test.dart
@@ -9,7 +9,9 @@
const A(foo);
}
-class B extends A with Mixin {
+class B extends A
+ with Mixin /// 01: compile-time error
+ {
const B(foo) : super(foo);
}
diff --git a/tests/language/language.status b/tests/language/language.status
index a04ad53..04b54c3 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -18,7 +18,6 @@
[ $compiler == dart2dart ]
mixin_super_constructor_named_test: Fail
mixin_super_constructor_positionals_test: Fail
-const_constructor_super_test/01: fail
[ $compiler == none ]
mixin_super_constructor_named_test: Fail
@@ -73,6 +72,11 @@
mixin_forwarding_constructor2_test: Fail # Issue 11888
mixin_typedef_constructor_test: Fail # Issue 11888
+mixin_type_parameter2_test: Fail # Issue 11888
+
+const_constructor_mixin_test/01: Fail # Issue 11917
+const_constructor_mixin2_test/01: Fail # Issue 11917
+const_constructor_mixin3_test/01: Fail # Issue 11917
[ $compiler == none && $unchecked ]
@@ -144,6 +148,7 @@
mixin_issue10216_2_test: Fail # VM issue
mixin_forwarding_constructor2_test: Fail # Issue 11888
mixin_typedef_constructor_test: Fail # Issue 11888
+mixin_type_parameter2_test: Fail # Issue 11888
mixin_with_two_implicit_constructors_test: Fail # Issue 11889
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 8e01e1e..85880b7 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -272,6 +272,10 @@
# test issue 11579, assignment, no setter
getter_no_setter_test/none: fail
+# test issue 11918: mixin and const constructor
+const_constructor_mixin_test/01: fail
+const_constructor_mixin3_test/01: fail
+
[ $compiler == dartanalyzer && $checked ]
factory1_test/00: fail
factory1_test/01: fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 26d084f..293c051 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -90,7 +90,6 @@
compile_time_constant_checked3_test/06: Fail, OK
[ $compiler == dart2js ]
-const_constructor_super_test/01: Fail # Const ctor calls non-const super ctor
function_type_alias6_test: Crash # dartbug.com/9792
branch_canonicalization_test: Fail # Issue 638.
div_with_power_of_two_test: Fail # Issue 8301.
diff --git a/tests/language/mixin_type_parameter1_test.dart b/tests/language/mixin_type_parameter1_test.dart
new file mode 100644
index 0000000..d591abd
--- /dev/null
+++ b/tests/language/mixin_type_parameter1_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class Mixin1<T> {
+}
+
+abstract class Mixin2<T> {
+}
+
+class A {
+}
+
+typedef MyTypedef<K, V> = A with Mixin1<K>, Mixin2<V>;
+
+class B<K, V> extends MyTypedef<K, V> {
+}
+
+main() {
+ var b = new B<num, String>();
+ Expect.isTrue(b is Mixin1<num>);
+ Expect.isTrue(b is! Mixin1<String>);
+ Expect.isTrue(b is Mixin2<String>);
+ Expect.isTrue(b is! Mixin2<num>);
+}
diff --git a/tests/language/mixin_type_parameter2_test.dart b/tests/language/mixin_type_parameter2_test.dart
new file mode 100644
index 0000000..27fe245
--- /dev/null
+++ b/tests/language/mixin_type_parameter2_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class Mixin1<T> {
+}
+
+abstract class Mixin2<T> {
+}
+
+class A {
+ A(foo);
+}
+
+typedef MyTypedef<K, V> = A with Mixin1<K>, Mixin2<V>;
+
+class B<K, V> extends MyTypedef<K, V> {
+ B(foo) : super(foo);
+}
+
+main() {
+ var b = new B<num, String>(null);
+ Expect.isTrue(b is Mixin1<num>);
+ Expect.isTrue(b is! Mixin1<String>);
+ Expect.isTrue(b is Mixin2<String>);
+ Expect.isTrue(b is! Mixin2<num>);
+}
diff --git a/tests/language/mixin_type_parameter3_test.dart b/tests/language/mixin_type_parameter3_test.dart
new file mode 100644
index 0000000..17da813
--- /dev/null
+++ b/tests/language/mixin_type_parameter3_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class Mixin1<T> {
+}
+
+abstract class Mixin2<T> {
+}
+
+class A {
+ A(foo);
+}
+
+class B<K, V> extends A with Mixin1<K>, Mixin2<V> {
+ B(foo) : super(foo);
+}
+
+main() {
+ var b = new B<num, String>(null);
+ Expect.isTrue(b is Mixin1<num>);
+ Expect.isTrue(b is! Mixin1<String>);
+ Expect.isTrue(b is Mixin2<String>);
+ Expect.isTrue(b is! Mixin2<num>);
+}
diff --git a/tests/lib/async/stream_controller_test.dart b/tests/lib/async/stream_controller_test.dart
index 3f2a48b..8f1d26a 100644
--- a/tests/lib/async/stream_controller_test.dart
+++ b/tests/lib/async/stream_controller_test.dart
@@ -416,9 +416,30 @@
Expect.isTrue(c.isClosed);
}
+void testStreamEquals() {
+ StreamController c;
+ c = new StreamController(sync: false);
+ Expect.equals(c.stream, c.stream);
+ c = new StreamController(sync: true);
+ Expect.equals(c.stream, c.stream);
+ c = new StreamController(sync: false, onListen:(){});
+ Expect.equals(c.stream, c.stream);
+ c = new StreamController(sync: true, onListen:(){});
+ Expect.equals(c.stream, c.stream);
+ c = new StreamController.broadcast(sync: false);
+ Expect.equals(c.stream, c.stream);
+ c = new StreamController.broadcast(sync: true);
+ Expect.equals(c.stream, c.stream);
+ c = new StreamController.broadcast(sync: false, onListen:(){});
+ Expect.equals(c.stream, c.stream);
+ c = new StreamController.broadcast(sync: true, onListen:(){});
+ Expect.equals(c.stream, c.stream);
+}
+
main() {
testMultiController();
testSingleController();
testExtraMethods();
testClosed();
+ testStreamEquals();
}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 0e75568..9b5952c 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -85,6 +85,7 @@
async/timer_not_available_test: Fail, OK # only meant to test when there is no way to
# implement timer (currently only in d8)
async/timer_isolate_test: Skip # See Issue 4997
+mirrors/native_class_test: Fail, OK # This test is meant to run in a browser.
[ $runtime == vm || ($compiler == none && $runtime == drt) ]
async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9001.
@@ -107,8 +108,6 @@
[ $arch == arm || $arch == simarm ]
-typed_data/float32x4_unbox_regress_test: Crash # Unimplemented
-typed_data/float32x4_list_test: Crash # Unimplemented
typed_data/float32x4_test: Crash # Unimplemented
[ $arch == mips ]
diff --git a/tests/lib/mirrors/native_class_test.dart b/tests/lib/mirrors/native_class_test.dart
new file mode 100644
index 0000000..b6171d0
--- /dev/null
+++ b/tests/lib/mirrors/native_class_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.native_class_test;
+
+import 'dart:html';
+
+@MirrorsUsed(targets: 'dart.dom.html.Element')
+import 'dart:mirrors';
+
+import 'stringify.dart';
+
+main() {
+ expect('s(dart.dom.html.Element)', reflectClass(Element).qualifiedName);
+ expect(
+ 's(dart.dom.html.Node)', reflectClass(Element).superclass.qualifiedName);
+ window.postMessage('unittest-suite-success', '*');
+}
diff --git a/tests/lib/typed_data/float32x4_list_test.dart b/tests/lib/typed_data/float32x4_list_test.dart
index 79ffdbc..0de9492 100644
--- a/tests/lib/typed_data/float32x4_list_test.dart
+++ b/tests/lib/typed_data/float32x4_list_test.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// VMOptions=--deoptimization_counter_threshold=1000
+// VMOptions=--deoptimization_counter_threshold=1000 --optimization-counter-threshold=10
// Library tag to be able to run in html test framework.
library float32x4_list_test;
@@ -40,49 +40,49 @@
testLoadStoreDeoptDriver() {
Float32x4List list = new Float32x4List(4);
Float32x4 value = new Float32x4(1.0, 2.0, 3.0, 4.0);
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStoreDeopt(list, 0, value);
}
try {
// Invalid index.
testLoadStoreDeopt(list, 5, value);
} catch (_) {}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStoreDeopt(list, 0, value);
}
try {
// null list.
testLoadStoreDeopt(null, 0, value);
} catch (_) {}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStoreDeopt(list, 0, value);
}
try {
// null value.
testLoadStoreDeopt(list, 0, null);
} catch (_) {}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStoreDeopt(list, 0, value);
}
try {
// non-smi index.
testLoadStoreDeopt(list, 3.14159, value);
} catch (_) {}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStoreDeopt(list, 0, value);
}
try {
// non-Float32x4 value.
testLoadStoreDeopt(list, 0, 4.toDouble());
} catch (_) {}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStoreDeopt(list, 0, value);
}
try {
// non-Float32x4List list.
testLoadStoreDeopt([new Float32x4(2.0, 3.0, 4.0, 5.0)], 0, value);
} catch (_) {}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStoreDeopt(list, 0, value);
}
}
@@ -112,7 +112,7 @@
var list;
list = new Float32x4List(8);
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStore(list);
}
@@ -121,13 +121,13 @@
floatList[i] = i.toDouble();
}
list = new Float32x4List.view(floatList);
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testView(list);
}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testLoadStore(list);
}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testListZero();
}
testLoadStoreDeoptDriver();
diff --git a/tests/lib/typed_data/float32x4_unbox_regress_test.dart b/tests/lib/typed_data/float32x4_unbox_regress_test.dart
index c20a6ea..e179f95 100644
--- a/tests/lib/typed_data/float32x4_unbox_regress_test.dart
+++ b/tests/lib/typed_data/float32x4_unbox_regress_test.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// VMOptions=--deoptimization_counter_threshold=1000
+// VMOptions=--deoptimization_counter_threshold=1000 --optimization-counter-threshold=10
// Library tag to be able to run in html test framework.
library float32x4_unbox_regress_test;
@@ -18,7 +18,7 @@
var value = new Float32x4(1.0, 2.0, 3.0, 4.0);
var smi = 12;
list = new Float32x4List(8);
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testListStore(list, 0, value);
}
@@ -41,7 +41,7 @@
var a = new Float32x4(1.0, 2.0, 3.0, 4.0);
var b = new Float32x4(2.0, 3.0, 4.0, 5.0);
var smi = 12;
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testAdd(a, b);
}
@@ -59,7 +59,7 @@
void testGetDeopt() {
var a = new Float32x4(1.0, 2.0, 3.0, 4.0);
var smi = 12;
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testGet(a);
}
@@ -68,7 +68,7 @@
} catch (_) {
}
- for (int i = 0; i < 3000; i++) {
+ for (int i = 0; i < 20; i++) {
testGet(a);
}
}
@@ -86,7 +86,7 @@
var b = new Float32x4(1.0, 2.1, 3.1, 4.0);
var smi = 12;
- for (int i = 0; i < 2000; i++) {
+ for (int i = 0; i < 20; i++) {
testComparison(a, b);
}
@@ -95,7 +95,7 @@
} catch (_) {
}
- for (int i = 0; i < 2000; i++) {
+ for (int i = 0; i < 20; i++) {
testComparison(a, b);
}
@@ -104,7 +104,7 @@
} catch (_) {
}
- for (int i = 0; i < 2000; i++) {
+ for (int i = 0; i < 20; i++) {
testComparison(a, b);
}
}
diff --git a/tests/standalone/io/raw_socket_test.dart b/tests/standalone/io/raw_socket_test.dart
index 1b1b23f..a61bccf 100644
--- a/tests/standalone/io/raw_socket_test.dart
+++ b/tests/standalone/io/raw_socket_test.dart
@@ -150,6 +150,7 @@
server.listen((client) {
int bytesRead = 0;
int bytesWritten = 0;
+ bool closedEventReceived = false;
List<int> data = new List<int>(messageSize);
client.writeEventsEnabled = false;
@@ -188,14 +189,20 @@
case RawSocketEvent.READ_CLOSED:
server.close();
break;
+ case RawSocketEvent.CLOSED:
+ Expect.isFalse(closedEventReceived);
+ closedEventReceived = true;
+ break;
default: throw "Unexpected event $event";
}
- });
+ },
+ onDone: () => Expect.isTrue(closedEventReceived));
});
RawSocket.connect("127.0.0.1", server.port).then((socket) {
int bytesRead = 0;
int bytesWritten = 0;
+ bool closedEventReceived = false;
List<int> data = createTestData();
socket.listen((event) {
@@ -229,10 +236,17 @@
verifyTestData(data);
socket.close();
break;
+ case RawSocketEvent.CLOSED:
+ Expect.isFalse(closedEventReceived);
+ closedEventReceived = true;
+ break;
default: throw "Unexpected event $event";
}
},
- onDone: () => port.close());
+ onDone: () {
+ Expect.isTrue(closedEventReceived);
+ port.close();
+ });
});
});
}
@@ -288,6 +302,7 @@
RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) {
Expect.isTrue(server.port > 0);
server.listen((client) {
+ bool closedEventReceived = false;
List<int> data = new List<int>.filled(messageSize, 0);
writeSubscription = client.listen((event) {
switch (event) {
@@ -312,12 +327,18 @@
client.close();
server.close();
break;
+ case RawSocketEvent.CLOSED:
+ Expect.isFalse(closedEventReceived);
+ closedEventReceived = true;
+ break;
default: throw "Unexpected event $event";
}
- });
+ },
+ onDone: () => Expect.isTrue(closedEventReceived));
});
RawSocket.connect("127.0.0.1", server.port).then((socket) {
+ bool closedEventReceived = false;
socket.writeEventsEnabled = false;
readSubscription = socket.listen((event) {
switch (event) {
@@ -343,10 +364,15 @@
case RawSocketEvent.WRITE:
throw "Unexpected write event";
case RawSocketEvent.READ_CLOSED:
- throw "Unexpected close event";
+ throw "Unexpected read closed event";
+ case RawSocketEvent.CLOSED:
+ Expect.isFalse(closedEventReceived);
+ closedEventReceived = true;
+ break;
default: throw "Unexpected event $event";
}
- });
+ },
+ onDone: () => Expect.isTrue(closedEventReceived));
readSubscription.pause();
connected.complete(true);
});
diff --git a/tests/standalone/io/raw_socket_typed_data_test.dart b/tests/standalone/io/raw_socket_typed_data_test.dart
index 61f9281..e843aba 100644
--- a/tests/standalone/io/raw_socket_typed_data_test.dart
+++ b/tests/standalone/io/raw_socket_typed_data_test.dart
@@ -28,6 +28,8 @@
client.close();
server.close();
break;
+ case RawSocketEvent.CLOSED:
+ break;
default: throw "Unexpected event $event";
}
});
@@ -71,6 +73,8 @@
break;
case RawSocketEvent.READ_CLOSED:
break;
+ case RawSocketEvent.CLOSED:
+ break;
default: throw "Unexpected event $event";
}
},
@@ -155,6 +159,8 @@
case RawSocketEvent.READ_CLOSED:
server.close();
break;
+ case RawSocketEvent.CLOSED:
+ break;
default: throw "Unexpected event $event";
}
});
@@ -194,6 +200,8 @@
verifyTestData(received);
socket.close();
break;
+ case RawSocketEvent.CLOSED:
+ break;
default: throw "Unexpected event $event";
}
},
diff --git a/tests/standalone/io/socket_exception_test.dart b/tests/standalone/io/socket_exception_test.dart
index 41290d6..f882b3e 100644
--- a/tests/standalone/io/socket_exception_test.dart
+++ b/tests/standalone/io/socket_exception_test.dart
@@ -118,7 +118,7 @@
static void clientSocketAddDestroyNoErrorTest() {
ServerSocket.bind("127.0.0.1", 0).then((server) {
server.listen((socket) {
- // Passive block data by not sobscribing to socket.
+ // Passive block data by not subscribing to socket.
});
Socket.connect("127.0.0.1", server.port).then((client) {
client.listen((data) {}, onDone: server.close);
diff --git a/tools/VERSION b/tools/VERSION
index 9a50ffe..de9958b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 6
-BUILD 7
+BUILD 8
PATCH 0
diff --git a/tools/publish_all_pkgs.py b/tools/publish_all_pkgs.py
index 2e3d181..6c302e2 100644
--- a/tools/publish_all_pkgs.py
+++ b/tools/publish_all_pkgs.py
@@ -21,13 +21,9 @@
pkgs_to_publish = []
for name in os.listdir('pkg'):
if os.path.isdir(os.path.join('pkg', name)):
- if (name != '.svn' and name != 'fixnum' and name != 'expect'):
+ if (name != '.svn' and name != 'expect'):
pkgs_to_publish.append(os.path.join('pkg', name))
- # Publish dart2js as an "unsupported" package.
- pkgs_to_publish.append(
- os.path.join('sdk', 'lib', '_internal', 'compiler'))
-
for pkg in pkgs_to_publish:
print "\n\nPublishing [32m%s[0m:\n-------------------------------" % pkg
subprocess.call(['python', 'tools/publish_pkg.py', pkg])