Update trunk to version 0.4.6.1
svn merge -r 21363:21386 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
--This line, and thsss below, will be ignored--
_M .
_M dart
M dart/editor/tools/plugins/com.google.dart.tools.deploy/themes/default.xml
M dart/editor/tools/plugins/com.google.dart.tools.deploy/themes/dartboard.xml
M dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/parser/SimpleParserTest.java
M dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/resolver/NonErrorResolverTest.java
M dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/resolver/StaticTypeWarningCodeTest.java
M dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/resolver/CompileTimeErrorCodeTest.java
M dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/resolver/ResolverTestCase.java
A + dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/resolver/TypePropagationTest.java
M dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/internal/resolver/TestAll.java
A + dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/internal/resolver/TypeOverrideManagerTest.java
M dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/internal/resolver/StaticTypeAnalyzerTest.java
A + dart/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/timing/SDKAnalysisTest.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/parser/Parser.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/element/member/ParameterMember.java
A + dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/element/member/FieldMember.java
A + dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/element/member/VariableMember.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/element/member/PropertyAccessorMember.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/LibraryResolver.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ElementResolver.java
A + dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/TypeOverrideManager.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/StaticTypeAnalyzer.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/ResolverVisitor.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/TypeResolverVisitor.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/scanner/AbstractScanner.java
M dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/error/StaticTypeWarningCode.java
M dart/editor/tools/plugins/com.google.dart.tools.debug.core/src/com/google/dart/tools/debug/core/webkit/WebkitConnection.java
M dart/editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/internal/analysis/model/ProjectImplTest.java
M dart/editor/tools/plugins/com.google.dart.tools.core_test/src/com/google/dart/tools/core/generator/GeneratorUtils.java
M dart/editor/tools/plugins/com.google.dart.tools.core/src/com/google/dart/tools/core/internal/analysis/model/ProjectImpl.java
M dart/editor/tools/plugins/com.google.dart.tools.core/src/com/google/dart/tools/core/pub/PubBuildParticipant.java
M dart/editor/util/plugins/com.google.dart.java2dart/resources/java_core.dart
M dart/tools/VERSION
M dart/tools/dom/scripts/fremontcutbuilder.py
M dart/tests/language/if_conversion_vm_test.dart
M dart/tests/language/language_dart2js.status
M dart/tests/language/language.status
M dart/tests/language/rethrow_test.dart
M dart/samples/third_party/todomvc/pubspec.yaml
M dart/samples/third_party/todomvc/web/todo_row.html
M dart/samples/third_party/todomvc/web/model.dart
M dart/samples/third_party/todomvc/web/editable_label.html
M dart/pkg/analyzer_experimental/lib/src/generated/java_core.dart
M dart/pkg/pkg.status
M dart/runtime/vm/os_win.cc
M dart/runtime/vm/simulator_mips.cc
M dart/runtime/vm/isolate.cc
M dart/runtime/vm/intrinsifier_x64.cc
M dart/runtime/vm/intrinsifier.h
M dart/runtime/vm/assembler_mips.h
M dart/runtime/vm/intrinsifier_ia32.cc
M dart/runtime/vm/parser.cc
M dart/runtime/vm/assembler_mips_test.cc
M dart/runtime/vm/constants_mips.h
M dart/runtime/vm/intermediate_language_x64.cc
M dart/runtime/vm/os_linux.cc
M dart/runtime/vm/object.h
M dart/runtime/vm/code_generator.cc
M dart/runtime/vm/token.h
M dart/runtime/vm/object.cc
M dart/runtime/vm/flow_graph_builder.cc
M dart/runtime/vm/simulator_mips.h
M dart/runtime/vm/disassembler_mips.cc
M dart/runtime/vm/os.h
M dart/runtime/vm/os_macos.cc
M dart/runtime/vm/intermediate_language.h
M dart/runtime/vm/intermediate_language_ia32.cc
M dart/runtime/vm/os_android.cc
M dart/runtime/platform/globals.h
git-svn-id: http://dart.googlecode.com/svn/trunk@21388 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/lib/src/generated/java_core.dart b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
index f293998..995fa42 100644
--- a/pkg/analyzer_experimental/lib/src/generated/java_core.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
@@ -375,7 +375,7 @@
_coPos--;
(_iterable as List).remove(_coPos);
} else if (_iterable is Set) {
- _iterable.remove(_current);
+ (_iterable as Set).remove(_current);
} else {
throw new StateError("Unsupported iterable ${_iterable.runtimeType}");
}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 0c0512c..959a310 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -9,6 +9,13 @@
# arithmetic natively, i.e., the VM.
fixnum/test/int_64_vm_test: Skip
+# Don't run any test-like files that show up in packages directories. It
+# shouldn't be necessary to run "pub install" in these packages, but if you do
+# it shouldn't break the tests.
+*/packages/*/*: Skip
+*/*/packages/*/*: Skip
+*/*/*/packages/*/*: Skip
+
# Skip non-test files ending with "_test".
scheduled_test/lib/*: Skip
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index ef56ad4..2d566bb 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -396,36 +396,6 @@
}
-// Some platforms do not support strndup. We add it below as necessary.
-#if defined(TARGET_OS_MACOS)
-// strndup has only been added to Mac OS X in 10.7. We are supplying
-// our own copy here.
-#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \
- __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
-#define NEEDS_STRNDUP 1
-#endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
-#elif defined(TARGET_OS_WINDOWS)
-#define NEEDS_STRNDUP 1
-#endif // defined(TARGET_OS_MACOS)
-
-#if defined(NEEDS_STRNDUP)
-// size_t used to match function signature on other platforms.
-inline char* strndup(const char* s, size_t n) {
- size_t len = strlen(s);
- if (n < len) {
- len = n;
- }
- char* result = reinterpret_cast<char*>(malloc(len + 1));
- if (!result) {
- return NULL;
- }
- result[len] = '\0';
- return reinterpret_cast<char*>(memcpy(result, s, len));
-}
-#endif // defined(NEEDS_STRNDUP)
-#undef NEEDS_STRNDUP
-
-
// A macro to ensure that memcpy cannot be called. memcpy does not handle
// overlapping memory regions. Even though this is well documented it seems
// to be used in error quite often. To avoid problems we disallow the direct
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 8f430a6..f21d030 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -223,12 +223,23 @@
}
// CPU instructions in alphabetical order.
+ void addd(FRegister fd, FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fd));
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_ADD);
+ }
+
void addiu(Register rt, Register rs, const Immediate& imm) {
ASSERT(Utils::IsInt(kImmBits, imm.value()));
const uint16_t imm_value = static_cast<uint16_t>(imm.value());
EmitIType(ADDIU, rs, rt, imm_value);
}
+ void adds(FRegister fd, FRegister fs, FRegister ft) {
+ EmitFpuRType(COP1, FMT_S, ft, fs, fd, COP1_ADD);
+ }
+
void addu(Register rd, Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, rd, 0, ADDU);
}
@@ -388,6 +399,11 @@
EmitLoadStore(LBU, rt, addr);
}
+ void ldc1(FRegister ft, const Address& addr) {
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuLoadStore(LDC1, ft, addr);
+ }
+
void lh(Register rt, const Address& addr) {
EmitLoadStore(LH, rt, addr);
}
@@ -406,6 +422,17 @@
EmitLoadStore(LW, rt, addr);
}
+ void lwc1(FRegister ft, const Address& addr) {
+ EmitFpuLoadStore(LWC1, ft, addr);
+ }
+
+ void mfc1(Register rt, FRegister fs) {
+ Emit(COP1 << kOpcodeShift |
+ COP1_MF << kCop1SubShift |
+ rt << kRtShift |
+ fs << kFsShift);
+ }
+
void mfhi(Register rd) {
EmitRType(SPECIAL, R0, R0, rd, 0, MFHI);
}
@@ -418,6 +445,12 @@
or_(rd, rs, ZR);
}
+ void movd(FRegister fd, FRegister fs) {
+ ASSERT(EvenFPURegister(fd));
+ ASSERT(EvenFPURegister(fs));
+ EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_MOV);
+ }
+
void movn(Register rd, Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, rd, 0, MOVN);
}
@@ -426,6 +459,17 @@
EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ);
}
+ void movs(FRegister fd, FRegister fs) {
+ EmitFpuRType(COP1, FMT_S, F0, fs, fd, COP1_MOV);
+ }
+
+ void mtc1(Register rt, FRegister fs) {
+ Emit(COP1 << kOpcodeShift |
+ COP1_MT << kCop1SubShift |
+ rt << kRtShift |
+ fs << kFsShift);
+ }
+
void mult(Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, R0, 0, MULT);
}
@@ -456,6 +500,11 @@
EmitLoadStore(SB, rt, addr);
}
+ void sdc1(FRegister ft, const Address& addr) {
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuLoadStore(SDC1, ft, addr);
+ }
+
void sh(Register rt, const Address& addr) {
EmitLoadStore(SH, rt, addr);
}
@@ -500,6 +549,10 @@
EmitLoadStore(SW, rt, addr);
}
+ void swc1(FRegister ft, const Address& addr) {
+ EmitFpuLoadStore(SWC1, ft, addr);
+ }
+
void xor_(Register rd, Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, rd, 0, XOR);
}
@@ -565,6 +618,36 @@
}
}
+ void LoadImmediate(FRegister rd, double value) {
+ ASSERT(EvenFPURegister(rd));
+ const int64_t ival = bit_cast<uint64_t, double>(value);
+ const int32_t low = Utils::Low32Bits(ival);
+ const int32_t high = Utils::High32Bits(ival);
+ if (low != 0) {
+ LoadImmediate(TMP1, low);
+ mtc1(TMP1, rd);
+ } else {
+ mtc1(ZR, rd);
+ }
+
+ if (high != 0) {
+ LoadImmediate(TMP1, high);
+ mtc1(TMP1, static_cast<FRegister>(rd + 1));
+ } else {
+ mtc1(ZR, static_cast<FRegister>(rd + 1));
+ }
+ }
+
+ void LoadImmediate(FRegister rd, float value) {
+ const int32_t ival = bit_cast<int32_t, float>(value);
+ if (ival == 0) {
+ mtc1(ZR, rd);
+ } else {
+ LoadImmediate(TMP1, ival);
+ mtc1(TMP1, rd);
+ }
+ }
+
void AddImmediate(Register rd, Register rs, int32_t value) {
if (Utils::IsInt(kImmBits, value)) {
addiu(rd, rs, Immediate(value));
@@ -734,6 +817,10 @@
GrowableArray<CodeComment*> comments_;
+ bool EvenFPURegister(FRegister reg) {
+ return (static_cast<int>(reg) & 1) == 0;
+ }
+
void Emit(int32_t value) {
// Emitting an instruction clears the delay slot state.
in_delay_slot_ = false;
@@ -761,6 +848,13 @@
addr.encoding());
}
+ void EmitFpuLoadStore(Opcode opcode, FRegister ft,
+ const Address &addr) {
+ Emit(opcode << kOpcodeShift |
+ ft << kFtShift |
+ addr.encoding());
+ }
+
void EmitRegImmType(Opcode opcode,
Register rs,
RtRegImm code,
@@ -790,6 +884,20 @@
func << kFunctionShift);
}
+ void EmitFpuRType(Opcode opcode,
+ Format fmt,
+ FRegister ft,
+ FRegister fs,
+ FRegister fd,
+ Cop1Function func) {
+ Emit(opcode << kOpcodeShift |
+ fmt << kFmtShift |
+ ft << kFtShift |
+ fs << kFsShift |
+ fd << kFdShift |
+ func << kCop1FnShift);
+ }
+
void EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
if (label->IsBound()) {
// Relative destination from an instruction after the branch.
diff --git a/runtime/vm/assembler_mips_test.cc b/runtime/vm/assembler_mips_test.cc
index 88d6472..0bd651c 100644
--- a/runtime/vm/assembler_mips_test.cc
+++ b/runtime/vm/assembler_mips_test.cc
@@ -1107,6 +1107,164 @@
EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
}
+
+ASSEMBLER_TEST_GENERATE(Mtc1Mfc1, assembler) {
+ __ mtc1(ZR, F0);
+ __ mfc1(V0, F0);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Mtc1Mfc1, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(0.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Addd, assembler) {
+ __ LoadImmediate(F0, 1.0);
+ __ LoadImmediate(F2, 2.0);
+ __ addd(F4, F0, F2);
+ __ mfc1(V0, F4);
+ __ mfc1(V1, F5);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Addd, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(3.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Adds, assembler) {
+ __ LoadImmediate(F0, 1.0f);
+ __ LoadImmediate(F2, 2.0f);
+ __ adds(F4, F0, F2);
+ __ mfc1(V0, F4);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Adds, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(3.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Movd, assembler) {
+ __ LoadImmediate(F0, 1.0);
+ __ movd(F2, F0);
+ __ mfc1(V0, F2);
+ __ mfc1(V1, F3);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Movd, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(1.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Movs, assembler) {
+ __ LoadImmediate(F0, 1.0f);
+ __ movd(F2, F0);
+ __ mfc1(V0, F2);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Movs, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(1.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Sdc1Ldc1, assembler) {
+ __ AddImmediate(SP, -8 * kWordSize);
+ __ LoadImmediate(T1, ~(8 - 1));
+ __ and_(T0, SP, T1); // Need 8 byte alignment.
+ __ LoadImmediate(F0, 1.0);
+ __ sdc1(F0, Address(T0));
+ __ ldc1(F2, Address(T0));
+ __ mfc1(V0, F2);
+ __ mfc1(V1, F3);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Sdc1Ldc1, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(1.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Swc1Lwc1, assembler) {
+ __ AddImmediate(SP, -1 * kWordSize);
+ __ LoadImmediate(F0, 1.0f);
+ __ swc1(F0, Address(SP));
+ __ lwc1(F1, Address(SP));
+ __ mfc1(V0, F1);
+ __ AddImmediate(SP, 1 * kWordSize);
+ __ Ret();
+}
+
+ASSEMBLER_TEST_RUN(Swc1Lwc1, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(1.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Adds_NaN, assembler) {
+ __ LoadImmediate(F0, 1.0f);
+ __ LoadImmediate(T0, 0x7f800001); // NaN
+ __ mtc1(T0, F2);
+ __ adds(F4, F0, F2);
+ __ mfc1(V0, F4);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Adds_NaN, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ float res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
+ EXPECT_EQ(isnan(res), true);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Adds_Inf, assembler) {
+ __ LoadImmediate(F0, 1.0f);
+ __ LoadImmediate(T0, 0x7f800000); // +inf
+ __ mtc1(T0, F2);
+ __ adds(F4, F0, F2);
+ __ mfc1(V0, F4);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Adds_Inf, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ float res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
+ EXPECT_EQ(isfinite(res), false);
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 4bbb77e..6ae0afa 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1014,8 +1014,9 @@
const MegamorphicCache& cache = MegamorphicCache::Handle(
isolate->megamorphic_cache_table()->Lookup(name, descriptor));
Class& cls = Class::Handle(receiver.clazz());
+ const bool is_null = cls.IsNullClass();
// For lookups treat null as an instance of class Object.
- if (cls.IsNullClass()) {
+ if (is_null) {
cls = isolate->object_store()->object_class();
}
ASSERT(!cls.IsNull());
@@ -1049,7 +1050,8 @@
if (instructions.IsNull()) return;
cache.EnsureCapacity();
- const Smi& class_id = Smi::Handle(Smi::New(cls.id()));
+ const Smi& class_id = Smi::Handle(Smi::New(
+ is_null ? static_cast<intptr_t>(kNullCid) : cls.id()));
cache.Insert(class_id, target);
return;
}
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index 9a47410..435b7d8 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -88,7 +88,8 @@
};
-// Values for double-precision floating point registers.
+// Values for floating point registers.
+// Double-precision values use register pairs.
enum FRegister {
F0 = 0,
F1 = 1,
@@ -161,6 +162,16 @@
const int kAbiPreservedCpuRegCount = 8;
+// FPU registers 20 - 31 are preserved across calls.
+const FRegister kAbiFirstPreservedFpuReg = F20;
+const FRegister kAbiLastPreservedFpuReg =
+ static_cast<FRegister>(kNumberOfFRegisters - 1);
+
+// FPU registers 0 - 19 are not preserved across calls.
+const FRegister kDartFirstVolatileFpuReg = F0;
+const FRegister kDartLastVolatileFpuReg = F19;
+const int kDartVolatileFpuRegCount = 20;
+
// Dart stack frame layout.
static const int kLastParamSlotIndex = 3;
static const int kFirstLocalSlotIndex = -2;
@@ -182,14 +193,26 @@
kOpcodeBits = 6,
kRsShift = 21,
kRsBits = 5,
+ kFmtShift = 21,
+ kFmtBits = 5,
kRtShift = 16,
kRtBits = 5,
+ kFtShift = 16,
+ kFtBits = 5,
kRdShift = 11,
kRdBits = 5,
+ kFsShift = 11,
+ kFsBits = 5,
kSaShift = 6,
kSaBits = 5,
+ kFdShift = 6,
+ kFdBits = 5,
kFunctionShift = 0,
kFunctionBits = 6,
+ kCop1FnShift = 0,
+ kCop1FnBits = 6,
+ kCop1SubShift = 21,
+ kCop1SubBits = 5,
kImmShift = 0,
kImmBits = 16,
kInstrShift = 0,
@@ -322,6 +345,24 @@
};
+enum Cop1Function {
+ COP1_ADD = 0,
+ COP1_MOV = 6,
+};
+
+enum Cop1Sub {
+ COP1_MF = 0,
+ COP1_MT = 4,
+};
+
+enum Format {
+ FMT_S = 16,
+ FMT_D = 17,
+ FMT_W = 20,
+ FMT_L = 21,
+ FMT_PS = 22,
+};
+
class Instr {
public:
enum {
@@ -371,6 +412,18 @@
return static_cast<Register>(Bits(kRdShift, kRdBits));
}
+ inline FRegister FsField() const {
+ return static_cast<FRegister>(Bits(kFsShift, kFsBits));
+ }
+
+ inline FRegister FtField() const {
+ return static_cast<FRegister>(Bits(kFtShift, kFtBits));
+ }
+
+ inline FRegister FdField() const {
+ return static_cast<FRegister>(Bits(kFdShift, kFdBits));
+ }
+
inline int SaField() const {
return Bits(kSaShift, kSaBits);
}
@@ -400,6 +453,22 @@
return (OpcodeField() == SPECIAL) && (FunctionField() == BREAK);
}
+ inline Cop1Function Cop1FunctionField() const {
+ return static_cast<Cop1Function>(Bits(kCop1FnShift, kCop1FnBits));
+ }
+
+ inline Cop1Sub Cop1SubField() const {
+ return static_cast<Cop1Sub>(Bits(kCop1SubShift, kCop1SubBits));
+ }
+
+ inline bool HasFormat() const {
+ return (OpcodeField() == COP1) && (Bit(25) == 1);
+ }
+
+ inline Format FormatField() const {
+ return static_cast<Format>(Bits(kFmtShift, kFmtBits));
+ }
+
// Instructions are read out of a code stream. The only way to get a
// reference to an instruction is to convert a pc. There is no way
// to allocate or create instances of class Instr.
diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
index 8233de7..717acbf 100644
--- a/runtime/vm/disassembler_mips.cc
+++ b/runtime/vm/disassembler_mips.cc
@@ -31,8 +31,11 @@
// Printing of common values.
void PrintRegister(Register reg);
+ void PrintFRegister(FRegister reg);
+ void PrintFormat(Instr* instr);
int FormatRegister(Instr* instr, const char* format);
+ int FormatFRegister(Instr* instr, const char* format);
int FormatOption(Instr* instr, const char* format);
void Format(Instr* instr, const char* format);
void Unknown(Instr* instr);
@@ -40,6 +43,7 @@
void DecodeSpecial(Instr* instr);
void DecodeSpecial2(Instr* instr);
void DecodeRegImm(Instr* instr);
+ void DecodeCop1(Instr* instr);
// Convenience functions.
char* get_buffer() const { return buffer_; }
@@ -79,6 +83,14 @@
};
+static const char* freg_names[kNumberOfFRegisters] = {
+ "f0" , "f1" , "f2" , "f3" , "f4" , "f5" , "f6" , "f7" ,
+ "f8" , "f9" , "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+};
+
+
void MIPSDecoder::PrintRegister(Register reg) {
ASSERT(0 <= reg);
ASSERT(reg < kNumberOfCpuRegisters);
@@ -86,6 +98,13 @@
}
+void MIPSDecoder::PrintFRegister(FRegister reg) {
+ ASSERT(0 <= reg);
+ ASSERT(reg < kNumberOfFRegisters);
+ Print(freg_names[reg]);
+}
+
+
// Handle all register based formatting in these functions to reduce the
// complexity of FormatOption.
int MIPSDecoder::FormatRegister(Instr* instr, const char* format) {
@@ -109,6 +128,57 @@
}
+int MIPSDecoder::FormatFRegister(Instr* instr, const char* format) {
+ ASSERT(format[0] == 'f');
+ switch (format[1]) {
+ case 's': { // 'fs: Fs register
+ PrintFRegister(instr->FsField());
+ return 2;
+ }
+ case 't': { // 'ft: Ft register
+ PrintFRegister(instr->FtField());
+ return 2;
+ }
+ case 'd': { // 'fd: Fd register
+ PrintFRegister(instr->FdField());
+ return 2;
+ }
+ }
+ UNREACHABLE();
+ return -1;
+}
+
+
+void MIPSDecoder::PrintFormat(Instr *instr) {
+ switch (instr->FormatField()) {
+ case FMT_S: {
+ Print("s");
+ break;
+ }
+ case FMT_D: {
+ Print("d");
+ break;
+ }
+ case FMT_W: {
+ Print("w");
+ break;
+ }
+ case FMT_L: {
+ Print("l");
+ break;
+ }
+ case FMT_PS: {
+ Print("ps");
+ break;
+ }
+ default: {
+ Print("unknown");
+ break;
+ }
+ }
+}
+
+
// FormatOption takes a formatting string and interprets it based on
// the current instructions. The format string points to the first
// character of the option string (the option escape has already been
@@ -170,6 +240,15 @@
case 'r': {
return FormatRegister(instr, format);
}
+ case 'f': {
+ if (format[1] == 'm') {
+ ASSERT(STRING_STARTS_WITH(format, "fmt"));
+ PrintFormat(instr);
+ return 3;
+ } else {
+ return FormatFRegister(instr, format);
+ }
+ }
case 's': {
ASSERT(STRING_STARTS_WITH(format, "sa"));
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
@@ -397,6 +476,51 @@
}
}
+void MIPSDecoder::DecodeCop1(Instr* instr) {
+ ASSERT(instr->OpcodeField() == COP1);
+ if (instr->HasFormat()) {
+ // If the rs field is a valid format, then the function field identifies
+ // the instruction.
+ switch (instr->Cop1FunctionField()) {
+ case COP1_ADD: {
+ Format(instr, "add.'fmt 'fd, 'fs, 'ft");
+ break;
+ }
+ case COP1_MOV: {
+ Format(instr, "mov.'fmt 'fd, 'fs");
+ break;
+ }
+ default: {
+ Unknown(instr);
+ break;
+ }
+ }
+ } else {
+ // If the rs field isn't a valid format, then it must be a sub-opcode.
+ switch (instr->Cop1SubField()) {
+ case COP1_MF: {
+ if (instr->Bits(0, 11) != 0) {
+ Unknown(instr);
+ } else {
+ Format(instr, "mfc1 'rt, 'fs");
+ }
+ break;
+ }
+ case COP1_MT: {
+ if (instr->Bits(0, 11) != 0) {
+ Unknown(instr);
+ } else {
+ Format(instr, "mtc1 'rt, 'fs");
+ }
+ break;
+ }
+ default: {
+ Unknown(instr);
+ break;
+ }
+ }
+ }
+}
void MIPSDecoder::InstructionDecode(Instr* instr) {
switch (instr->OpcodeField()) {
@@ -412,6 +536,10 @@
DecodeRegImm(instr);
break;
}
+ case COP1: {
+ DecodeCop1(instr);
+ break;
+ }
case ADDIU: {
Format(instr, "addiu 'rt, 'rs, 'imms");
break;
@@ -460,6 +588,10 @@
Format(instr, "lbu 'rt, 'imms('rs)");
break;
}
+ case LDC1: {
+ Format(instr, "ldc1 'ft, 'imms('rs)");
+ break;
+ }
case LH: {
Format(instr, "lh 'rt, 'imms('rs)");
break;
@@ -472,6 +604,10 @@
Format(instr, "lw 'rt, 'imms('rs)");
break;
}
+ case LWC1: {
+ Format(instr, "lwc1 'ft, 'imms('rs)");
+ break;
+ }
case ORI: {
Format(instr, "ori 'rt, 'rs, 'immu");
break;
@@ -484,10 +620,18 @@
Format(instr, "sh 'rt, 'imms('rs)");
break;
}
+ case SDC1: {
+ Format(instr, "sdc1 'ft, 'imms('rs)");
+ break;
+ }
case SW: {
Format(instr, "sw 'rt, 'imms('rs)");
break;
}
+ case SWC1: {
+ Format(instr, "swc1 'ft, 'imms('rs)");
+ break;
+ }
default: {
Unknown(instr);
break;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 00b3932..21a3a35 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2079,18 +2079,18 @@
#define RECOGNIZED_LIST_FACTORY_LIST(V) \
V(ObjectArrayFactory, kArrayCid, 97987288) \
V(GrowableObjectArrayWithData, kGrowableObjectArrayCid, 816132033) \
- V(GrowableObjectArrayFactory, kGrowableObjectArrayCid, 224791427) \
- V(Int8ListFactory, kTypedDataInt8ArrayCid, 1178498933) \
- V(Uint8ListFactory, kTypedDataUint8ArrayCid, 996047641) \
- V(Uint8ClampedListFactory, kTypedDataUint8ClampedArrayCid, 1504313643) \
- V(Int16ListFactory, kTypedDataInt16ArrayCid, 1595869856) \
- V(Uint16ListFactory, kTypedDataUint16ArrayCid, 665298027) \
- V(Int32ListFactory, kTypedDataInt32ArrayCid, 728173538) \
- V(Uint32ListFactory, kTypedDataUint32ArrayCid, 352036624) \
- V(Int64ListFactory, kTypedDataInt64ArrayCid, 105935265) \
- V(Uint64ListFactory, kTypedDataUint64ArrayCid, 943403644) \
- V(Float64ListFactory, kTypedDataFloat64ArrayCid, 348533743) \
- V(Float32ListFactory, kTypedDataFloat32ArrayCid, 1830794379) \
+ V(GrowableObjectArrayFactory, kGrowableObjectArrayCid, 369608996) \
+ V(Int8ListFactory, kTypedDataInt8ArrayCid, 2066002614) \
+ V(Uint8ListFactory, kTypedDataUint8ArrayCid, 1883551322) \
+ V(Uint8ClampedListFactory, kTypedDataUint8ClampedArrayCid, 244333676) \
+ V(Int16ListFactory, kTypedDataInt16ArrayCid, 335889889) \
+ V(Uint16ListFactory, kTypedDataUint16ArrayCid, 1552801708) \
+ V(Int32ListFactory, kTypedDataInt32ArrayCid, 1615677219) \
+ V(Uint32ListFactory, kTypedDataUint32ArrayCid, 1239540305) \
+ V(Int64ListFactory, kTypedDataInt64ArrayCid, 993438946) \
+ V(Uint64ListFactory, kTypedDataUint64ArrayCid, 1830907325) \
+ V(Float64ListFactory, kTypedDataFloat64ArrayCid, 1236037424) \
+ V(Float32ListFactory, kTypedDataFloat32ArrayCid, 570814412) \
// Class that recognizes factories and returns corresponding result cid.
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 9ac45c1..fd21acf 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -59,16 +59,16 @@
V(_GrowableObjectArray, get:length, GrowableArrayLength, 725548050) \
V(_GrowableObjectArray, get:_capacity, GrowableArrayCapacity, 725548050) \
V(_StringBase, get:length, StringBaseLength, 320803993) \
- V(_StringBase, get:isEmpty, StringBaseIsEmpty, 110632481) \
+ V(_StringBase, get:isEmpty, StringBaseIsEmpty, 1026765313) \
V(_StringBase, codeUnitAt, StringBaseCodeUnitAt, 984449525) \
V(_StringBase, [], StringBaseCharAt, 1062366987) \
- V(_IntegerImplementation, toDouble, IntegerToDouble, 927078825) \
+ V(_IntegerImplementation, toDouble, IntegerToDouble, 1267108971) \
V(_Double, toInt, DoubleToInteger, 362666636) \
V(_Double, truncateToDouble, DoubleTruncate, 620870996) \
V(_Double, roundToDouble, DoubleRound, 620870996) \
V(_Double, floorToDouble, DoubleFloor, 620870996) \
V(_Double, ceilToDouble, DoubleCeil, 620870996) \
- V(_Double, pow, DoublePow, 1229411686) \
+ V(_Double, pow, DoublePow, 631903778) \
V(_Double, _modulo, DoubleMod, 437099337) \
V(::, sqrt, MathSqrt, 1662640002) \
@@ -2774,7 +2774,10 @@
virtual bool HasSideEffect() const { return false; }
virtual bool AttributesEqual(Instruction* other) const {
- return kind_ == other->AsIfThenElse()->kind_;
+ IfThenElseInstr* other_if_then_else = other->AsIfThenElse();
+ return (kind_ == other_if_then_else->kind_) &&
+ (if_true_ == other_if_then_else->if_true_) &&
+ (if_false_ == other_if_then_else->if_false_);
}
virtual bool AffectedBySideEffect() const {
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 96e14fa..689f965 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -3724,12 +3724,6 @@
}
-// Detect pattern when one value is increment of another.
-static bool IsIncrementKind(intptr_t v1, intptr_t v2) {
- return ((v1 == v2 + 1) || (v1 + 1 == v2));
-}
-
-
bool IfThenElseInstr::IsSupported() {
return true;
}
@@ -3752,12 +3746,7 @@
return false;
}
- if (IsPowerOfTwoKind(v1_value, v2_value) ||
- IsIncrementKind(v1_value, v2_value)) {
- return true;
- }
-
- return false;
+ return true;
}
@@ -3803,22 +3792,38 @@
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
- const intptr_t base = Utils::Minimum(if_true_, if_false_);
+ intptr_t true_value = if_true_;
+ intptr_t false_value = if_false_;
- if (if_true_ == base) {
- // We need to have zero in EDX on true_condition.
- true_condition = NegateCondition(true_condition);
+ if (is_power_of_two_kind) {
+ if (true_value == 0) {
+ // We need to have zero in EDX on true_condition.
+ true_condition = NegateCondition(true_condition);
+ }
+ } else {
+ if (true_value == 0) {
+ // Swap values so that false_value is zero.
+ intptr_t temp = true_value;
+ true_value = false_value;
+ false_value = temp;
+ } else {
+ true_condition = NegateCondition(true_condition);
+ }
}
__ setcc(true_condition, DL);
if (is_power_of_two_kind) {
const intptr_t shift =
- Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_));
+ Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
__ shll(EDX, Immediate(shift + kSmiTagSize));
} else {
- ASSERT(kSmiTagSize == 1);
- __ leal(EDX, Address(EDX, TIMES_2, base << kSmiTagSize));
+ __ subl(EDX, Immediate(1));
+ __ andl(EDX, Immediate(
+ Smi::RawValue(true_value) - Smi::RawValue(false_value)));
+ if (false_value != 0) {
+ __ addl(EDX, Immediate(Smi::RawValue(false_value)));
+ }
}
}
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 264c3199..3a7a6e1 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -155,12 +155,6 @@
}
-// Detect pattern when one value is increment of another.
-static bool IsIncrementKind(intptr_t v1, intptr_t v2) {
- return ((v1 == v2 + 1) || (v1 + 1 == v2));
-}
-
-
bool IfThenElseInstr::IsSupported() {
return true;
}
@@ -183,11 +177,6 @@
return false;
}
- if (IsPowerOfTwoKind(v1_value, v2_value) ||
- IsIncrementKind(v1_value, v2_value)) {
- return true;
- }
-
return false;
}
@@ -234,22 +223,38 @@
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
- const intptr_t base = Utils::Minimum(if_true_, if_false_);
+ intptr_t true_value = if_true_;
+ intptr_t false_value = if_false_;
- if (if_true_ == base) {
- // We need to have zero in RDX on true_condition.
- true_condition = NegateCondition(true_condition);
+ if (is_power_of_two_kind) {
+ if (true_value == 0) {
+ // We need to have zero in RDX on true_condition.
+ true_condition = NegateCondition(true_condition);
+ }
+ } else {
+ if (true_value == 0) {
+ // Swap values so that false_value is zero.
+ intptr_t temp = true_value;
+ true_value = false_value;
+ false_value = temp;
+ } else {
+ true_condition = NegateCondition(true_condition);
+ }
}
__ setcc(true_condition, DL);
if (is_power_of_two_kind) {
const intptr_t shift =
- Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_));
+ Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
__ shlq(RDX, Immediate(shift + kSmiTagSize));
} else {
- ASSERT(kSmiTagSize == 1);
- __ leaq(RDX, Address(RDX, TIMES_2, base << kSmiTagSize));
+ __ subq(RDX, Immediate(1));
+ __ andq(RDX, Immediate(
+ Smi::RawValue(true_value) - Smi::RawValue(false_value)));
+ if (false_value != 0) {
+ __ addq(RDX, Immediate(Smi::RawValue(false_value)));
+ }
}
}
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 0716629..0a1afd9 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -17,47 +17,47 @@
// build and run to get the correct fingerprint from the mismatch error.
#define CORE_LIB_INTRINSIC_LIST(V) \
V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger, 726019207)\
- V(_IntegerImplementation, +, Integer_add, 25837296) \
+ V(_IntegerImplementation, +, Integer_add, 1768648592) \
V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger, 726019207)\
- V(_IntegerImplementation, -, Integer_sub, 1697139934) \
+ V(_IntegerImplementation, -, Integer_sub, 1292467582) \
V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger, 726019207)\
- V(_IntegerImplementation, *, Integer_mul, 110370751) \
- V(_IntegerImplementation, %, Integer_modulo, 108639519) \
- V(_IntegerImplementation, ~/, Integer_truncDivide, 1187354250) \
- V(_IntegerImplementation, unary-, Integer_negate, 675709702) \
+ V(_IntegerImplementation, *, Integer_mul, 1853182047) \
+ V(_IntegerImplementation, %, Integer_modulo, 1211518976) \
+ V(_IntegerImplementation, ~/, Integer_truncDivide, 142750059) \
+ V(_IntegerImplementation, unary-, Integer_negate, 676633254) \
V(_IntegerImplementation, _bitAndFromInteger, \
Integer_bitAndFromInteger, 726019207) \
- V(_IntegerImplementation, &, Integer_bitAnd, 759019505) \
+ V(_IntegerImplementation, &, Integer_bitAnd, 354347153) \
V(_IntegerImplementation, _bitOrFromInteger, \
Integer_bitOrFromInteger, 726019207) \
- V(_IntegerImplementation, |, Integer_bitOr, 1280367298) \
+ V(_IntegerImplementation, |, Integer_bitOr, 875694946) \
V(_IntegerImplementation, _bitXorFromInteger, \
Integer_bitXorFromInteger, 726019207) \
- V(_IntegerImplementation, ^, Integer_bitXor, 686827811) \
+ V(_IntegerImplementation, ^, Integer_bitXor, 282155459) \
V(_IntegerImplementation, \
_greaterThanFromInteger, \
Integer_greaterThanFromInt, 79222670) \
- V(_IntegerImplementation, >, Integer_greaterThan, 866987265) \
- V(_IntegerImplementation, ==, Integer_equal, 408178104) \
+ V(_IntegerImplementation, >, Integer_greaterThan, 462314913) \
+ V(_IntegerImplementation, ==, Integer_equal, 1424765465) \
V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger, 79222670) \
- V(_IntegerImplementation, <, Integer_lessThan, 1423914919) \
- V(_IntegerImplementation, <=, Integer_lessEqualThan, 890963352) \
- V(_IntegerImplementation, >=, Integer_greaterEqualThan, 890993143) \
- V(_IntegerImplementation, <<, Integer_shl, 1600590181) \
- V(_IntegerImplementation, >>, Integer_sar, 237416447) \
+ V(_IntegerImplementation, <, Integer_lessThan, 1424838471) \
+ V(_IntegerImplementation, <=, Integer_lessEqualThan, 949016155) \
+ V(_IntegerImplementation, >=, Integer_greaterEqualThan, 949045946) \
+ V(_IntegerImplementation, <<, Integer_shl, 1195917829) \
+ V(_IntegerImplementation, >>, Integer_sar, 1980227743) \
V(_Smi, ~, Smi_bitNegate, 882629793) \
- V(_Double, >, Double_greaterThan, 498448864) \
- V(_Double, >=, Double_greaterEqualThan, 1126476149) \
- V(_Double, <, Double_lessThan, 1595327781) \
- V(_Double, <=, Double_lessEqualThan, 1126446358) \
- V(_Double, ==, Double_equal, 48480576) \
- V(_Double, +, Double_add, 407090160) \
- V(_Double, -, Double_sub, 1801868246) \
- V(_Double, *, Double_mul, 984784342) \
- V(_Double, /, Double_div, 1399344917) \
+ V(_Double, >, Double_greaterThan, 301935359) \
+ V(_Double, >=, Double_greaterEqualThan, 1184528952) \
+ V(_Double, <, Double_lessThan, 1596251333) \
+ V(_Double, <=, Double_lessEqualThan, 1184499161) \
+ V(_Double, ==, Double_equal, 1706047712) \
+ V(_Double, +, Double_add, 210576655) \
+ V(_Double, -, Double_sub, 1605354741) \
+ V(_Double, *, Double_mul, 788270837) \
+ V(_Double, /, Double_div, 1202831412) \
V(_Double, get:isNaN, Double_getIsNaN, 54462366) \
V(_Double, get:isNegative, Double_getIsNegative, 54462366) \
- V(_Double, _mulFromInteger, Double_mulFromInteger, 353781714) \
+ V(_Double, _mulFromInteger, Double_mulFromInteger, 704314034) \
V(_Double, .fromInteger, Double_fromInteger, 842078193) \
V(_Double, toInt, Double_toInt, 362666636) \
V(_ObjectArray, ., ObjectArray_Allocate, 97987288) \
@@ -71,12 +71,12 @@
V(_GrowableObjectArray, []=, GrowableArray_setIndexed, 1048007636) \
V(_GrowableObjectArray, _setLength, GrowableArray_setLength, 796709584) \
V(_GrowableObjectArray, _setData, GrowableArray_setData, 629110947) \
- V(_GrowableObjectArray, add, GrowableArray_add, 2139340847) \
+ V(_GrowableObjectArray, add, GrowableArray_add, 1904852879) \
V(_ImmutableArray, [], ImmutableArray_getIndexed, 486821199) \
V(_ImmutableArray, get:length, ImmutableArray_getLength, 433698233) \
- V(Object, ==, Object_equal, 2126867222) \
+ V(Object, ==, Object_equal, 2126897013) \
V(_StringBase, get:hashCode, String_getHashCode, 320803993) \
- V(_StringBase, get:isEmpty, String_getIsEmpty, 110632481) \
+ V(_StringBase, get:isEmpty, String_getIsEmpty, 1026765313) \
V(_StringBase, get:length, String_getLength, 320803993) \
V(_StringBase, codeUnitAt, String_codeUnitAt, 984449525) \
V(_OneByteString, get:hashCode, OneByteString_getHashCode, 682660413) \
@@ -104,18 +104,18 @@
V(_Float32Array, _new, TypedData_Float32Array_new, 1053133615) \
V(_Float64Array, _new, TypedData_Float64Array_new, 936673303) \
V(_Float32x4Array, _new, TypedData_Float32x4Array_new, 212088644) \
- V(_Int8Array, ., TypedData_Int8Array_factory, 632939448) \
- V(_Uint8Array, ., TypedData_Uint8Array_factory, 1942390430) \
- V(_Uint8ClampedArray, ., TypedData_Uint8ClampedArray_factory, 1447100174) \
- V(_Int16Array, ., TypedData_Int16Array_factory, 1997238698) \
- V(_Uint16Array, ., TypedData_Uint16Array_factory, 672422545) \
- V(_Int32Array, ., TypedData_Int32Array_factory, 504367176) \
- V(_Uint32Array, ., TypedData_Uint32Array_factory, 31896861) \
- V(_Int64Array, ., TypedData_Int64Array_factory, 702290418) \
- V(_Uint64Array, ., TypedData_Uint64Array_factory, 59820857) \
- V(_Float32Array, ., TypedData_Float32Array_factory, 1040427868) \
- V(_Float64Array, ., TypedData_Float64Array_factory, 969149770) \
- V(_Float32x4Array, ., TypedData_Float32x4Array_factory, 175242544) \
+ V(_Int8Array, ., TypedData_Int8Array_factory, 156009974) \
+ V(_Uint8Array, ., TypedData_Uint8Array_factory, 1465460956) \
+ V(_Uint8ClampedArray, ., TypedData_Uint8ClampedArray_factory, 970170700) \
+ V(_Int16Array, ., TypedData_Int16Array_factory, 1520309224) \
+ V(_Uint16Array, ., TypedData_Uint16Array_factory, 195493071) \
+ V(_Int32Array, ., TypedData_Int32Array_factory, 27437702) \
+ V(_Uint32Array, ., TypedData_Uint32Array_factory, 1702451035) \
+ V(_Int64Array, ., TypedData_Int64Array_factory, 225360944) \
+ V(_Uint64Array, ., TypedData_Uint64Array_factory, 1730375031) \
+ V(_Float32Array, ., TypedData_Float32Array_factory, 563498394) \
+ V(_Float64Array, ., TypedData_Float64Array_factory, 492220296) \
+ V(_Float32x4Array, ., TypedData_Float32x4Array_factory, 1845796718) \
// TODO(srdjan): Implement _FixedSizeArrayIterator, get:current and
// _FixedSizeArrayIterator, moveNext.
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 3a00aed..f99d22b 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -384,7 +384,8 @@
}
-// Set length of growable object array.
+// Set length of growable object array. The length cannot
+// be greater than the length of the data container.
// On stack: growable array (+2), length (+1), return-address (+0).
bool Intrinsifier::GrowableArray_setLength(Assembler* assembler) {
Label fall_through;
@@ -392,9 +393,6 @@
__ movl(EBX, Address(ESP, + 1 * kWordSize)); // Length value.
__ testl(EBX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length.
- __ movl(EDI, FieldAddress(EAX, GrowableObjectArray::data_offset()));
- __ cmpl(EBX, FieldAddress(EDI, Array::length_offset()));
- __ j(ABOVE, &fall_through, Assembler::kNearJump);
__ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), EBX);
__ ret();
__ Bind(&fall_through);
@@ -1589,14 +1587,21 @@
__ movl(ECX, Address(ESP, + kEndIndexOffset));
__ SmiUntag(ECX);
__ subl(ECX, EBX);
+ __ xorl(EDX, EDX);
+ // EDI: Start address to copy from (untagged).
// ECX: Untagged number of bytes to copy.
- ASSERT(CTX == ESI);
- __ pushl(ESI); // Preserve CTX.
- __ movl(ESI, EDI); // from.
- __ leal(EDI, FieldAddress(EAX, OneByteString::data_offset())); // to.
- __ rep_movsb();
- __ popl(ESI); // Restore CTX.
-
+ // EAX: Tagged result string.
+ // EDX: Loop counter.
+ // EBX: Scratch register.
+ Label loop, check;
+ __ jmp(&check, Assembler::kNearJump);
+ __ Bind(&loop);
+ __ movzxb(EBX, Address(EDI, EDX, TIMES_1, 0));
+ __ movb(FieldAddress(EAX, EDX, TIMES_1, OneByteString::data_offset()), BL);
+ __ incl(EDX);
+ __ Bind(&check);
+ __ cmpl(EDX, ECX);
+ __ j(LESS, &loop, Assembler::kNearJump);
__ ret();
__ Bind(&fall_through);
return false;
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 3e65b9f..d92086b 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -338,7 +338,8 @@
}
-// Set length of growable object array.
+// Set length of growable object array. The length cannot
+// be greater than the length of the data container.
// On stack: growable array (+2), length (+1), return-address (+0).
bool Intrinsifier::GrowableArray_setLength(Assembler* assembler) {
Label fall_through;
@@ -346,9 +347,6 @@
__ movq(RCX, Address(RSP, + 1 * kWordSize)); // Length value.
__ testq(RCX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length.
- __ movq(RDX, FieldAddress(RAX, GrowableObjectArray::data_offset()));
- __ cmpq(RCX, FieldAddress(RDX, Array::length_offset()));
- __ j(ABOVE, &fall_through, Assembler::kNearJump);
__ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()), RCX);
__ ret();
__ Bind(&fall_through);
@@ -1507,16 +1505,26 @@
__ movq(RBX, Address(RSP, + kStartIndexOffset));
__ SmiUntag(RBX);
__ leaq(RSI, FieldAddress(RSI, RBX, TIMES_1, OneByteString::data_offset()));
- // RDI: Start address to copy from (untagged).
+ // RSI: Start address to copy from (untagged).
// RBX: Untagged start index.
__ movq(RCX, Address(RSP, + kEndIndexOffset));
__ SmiUntag(RCX);
__ subq(RCX, RBX);
+ __ xorq(RDX, RDX);
+ // RSI: Start address to copy from (untagged).
// RCX: Untagged number of bytes to copy.
-
- __ leaq(RDI, FieldAddress(RAX, OneByteString::data_offset())); // to.
- __ rep_movsb();
-
+ // RAX: Tagged result string
+ // RDX: Loop counter.
+ // RBX: Scratch register.
+ Label loop, check;
+ __ jmp(&check, Assembler::kNearJump);
+ __ Bind(&loop);
+ __ movzxb(RBX, Address(RSI, RDX, TIMES_1, 0));
+ __ movb(FieldAddress(RAX, RDX, TIMES_1, OneByteString::data_offset()), RBX);
+ __ incq(RDX);
+ __ Bind(&check);
+ __ cmpq(RDX, RCX);
+ __ j(LESS, &loop, Assembler::kNearJump);
__ ret();
__ Bind(&fall_through);
return false;
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index d67b4e1..a4369d9 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -828,7 +828,7 @@
code.is_optimized() ? "false" : "true");
}
buffer.Printf("]}");
- isolate->stacktrace_ = strndup(buffer.buf(), buffer.length());
+ isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length());
ml.Notify();
return true;
}
@@ -872,7 +872,7 @@
var_name.ToCString(), token_pos, end_pos, value.ToCString());
}
buffer.Printf("]}");
- isolate->stacktrace_ = strndup(buffer.buf(), buffer.length());
+ isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length());
ml.Notify();
return true;
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ded68b8..8b7c816 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4461,14 +4461,22 @@
}
-bool Function::CheckSourceFingerprint(intptr_t fp) const {
+bool Function::CheckSourceFingerprint(int32_t fp) const {
if (SourceFingerprint() != fp) {
- OS::Print("FP mismatch while recognizing method %s:"
- " expecting %"Pd" found %d\n",
- ToFullyQualifiedCString(),
- fp,
- SourceFingerprint());
- return false;
+ const bool recalculatingFingerprints = false;
+ if (recalculatingFingerprints) {
+ // This output can be copied into a file, then used with sed
+ // to replace the old values.
+ // sed -i .bak -f /tmp/newkeys runtime/vm/intrinsifier.h
+ OS::Print("s/%d/%d/\n", fp, SourceFingerprint());
+ } else {
+ OS::Print("FP mismatch while recognizing method %s:"
+ " expecting %d found %d\n",
+ ToFullyQualifiedCString(),
+ fp,
+ SourceFingerprint());
+ return false;
+ }
}
return true;
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 5473069..a81aaa0 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1588,7 +1588,7 @@
int32_t SourceFingerprint() const;
// Return false and report an error if the fingerprint does not match.
- bool CheckSourceFingerprint(intptr_t fp) const;
+ bool CheckSourceFingerprint(int32_t fp) const;
static const int kCtorPhaseInit = 1 << 0;
static const int kCtorPhaseBody = 1 << 1;
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index 52e575d..a41e3bd 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -81,6 +81,9 @@
// Debug break.
static void DebugBreak();
+ // Not all platform support strndup.
+ static char* StrNDup(const char* s, intptr_t n);
+
// Print formatted output to stdout/stderr for debugging.
static void Print(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
static void PrintErr(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 6b19878..c77ff51 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -318,6 +318,11 @@
}
+char* OS::StrNDup(const char* s, intptr_t n) {
+ return strndup(s, n);
+}
+
+
void OS::Print(const char* format, ...) {
va_list args;
va_start(args, format);
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index cf113b6..9d8a8f7 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -413,6 +413,11 @@
}
+char* OS::StrNDup(const char* s, intptr_t n) {
+ return strndup(s, n);
+}
+
+
void OS::Print(const char* format, ...) {
va_list args;
va_start(args, format);
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index fd530de..cd0b53e 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -135,6 +135,30 @@
}
+char* OS::StrNDup(const char* s, intptr_t n) {
+ // strndup has only been added to Mac OS X in 10.7. We are supplying
+ // our own copy here if needed.
+#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
+ intptr_t len = strlen(s);
+ if ((n < 0) || (len < 0)) {
+ return NULL;
+ }
+ if (n < len) {
+ len = n;
+ }
+ char* result = reinterpret_cast<char*>(malloc(len + 1));
+ if (result == NULL) {
+ return NULL;
+ }
+ result[len] = '\0';
+ return reinterpret_cast<char*>(memmove(result, s, len));
+#else // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+ return strndup(s, n);
+#endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+}
+
+
void OS::Print(const char* format, ...) {
va_list args;
va_start(args, format);
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index 2e1a398..1c81e16 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -178,6 +178,23 @@
}
+char* OS::StrNDup(const char* s, intptr_t n) {
+ intptr_t len = strlen(s);
+ if ((n < 0) || (len < 0)) {
+ return NULL;
+ }
+ if (n < len) {
+ len = n;
+ }
+ char* result = reinterpret_cast<char*>(malloc(len + 1));
+ if (result == NULL) {
+ return NULL;
+ }
+ result[len] = '\0';
+ return reinterpret_cast<char*>(memcpy(result, s, len));
+}
+
+
void OS::Print(const char* format, ...) {
va_list args;
va_start(args, format);
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 83dcbcf..09da9c6 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -6411,10 +6411,12 @@
} else if (CurrentToken() == Token::kSEMICOLON) {
// Empty statement, nothing to do.
ConsumeToken();
- } else if ((CurrentToken() == Token::kTHROW) &&
- (LookaheadToken(1) == Token::kSEMICOLON)) {
+ } else if ((CurrentToken() == Token::kRETHROW) ||
+ ((CurrentToken() == Token::kTHROW) &&
+ (LookaheadToken(1) == Token::kSEMICOLON))) {
// Rethrow of current exception. Throwing of an exception object
// is an expression and is handled in ParseExpr().
+ // TODO(hausner): remove support for 'throw;'.
ConsumeToken();
ExpectSemicolon();
// Check if it is ok to do a rethrow.
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index c868443..7405738 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -642,8 +642,7 @@
}
-// Sets the register in the architecture state. It will also deal with updating
-// Simulator internal state for special registers such as PC.
+// Sets the register in the architecture state.
void Simulator::set_register(Register reg, int32_t value) {
if (reg != R0) {
registers_[reg] = value;
@@ -651,8 +650,36 @@
}
-// Get the register from the architecture state. This function does handle
-// the special case of accessing the PC register.
+void Simulator::set_fregister(FRegister reg, int32_t value) {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ fregisters_[reg] = value;
+}
+
+
+void Simulator::set_fregister_float(FRegister reg, float value) {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ fregisters_[reg] = bit_cast<int32_t, float>(value);
+}
+
+
+void Simulator::set_fregister_long(FRegister reg, int64_t value) {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ ASSERT((reg & 1) == 0);
+ fregisters_[reg] = Utils::Low32Bits(value);
+ fregisters_[reg + 1] = Utils::High32Bits(value);
+}
+
+
+void Simulator::set_fregister_double(FRegister reg, double value) {
+ const int64_t ival = bit_cast<int64_t, double>(value);
+ set_fregister_long(reg, ival);
+}
+
+
+// Get the register from the architecture state.
int32_t Simulator::get_register(Register reg) const {
if (reg == R0) {
return 0;
@@ -661,15 +688,36 @@
}
-void Simulator::set_fregister(FRegister reg, double value) {
+int32_t Simulator::get_fregister(FRegister reg) const {
ASSERT((reg >= 0) && (reg < kNumberOfFRegisters));
- fregisters_[reg] = value;
+ return fregisters_[reg];
}
-double Simulator::get_fregister(FRegister reg) const {
- ASSERT((reg >= 0) && (reg < kNumberOfFRegisters));
- return fregisters_[reg];
+float Simulator::get_fregister_float(FRegister reg) const {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ return bit_cast<float, int32_t>(fregisters_[reg]);
+}
+
+
+int64_t Simulator::get_fregister_long(FRegister reg) const {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ ASSERT((reg & 1) == 0);
+ const int32_t low = fregisters_[reg];
+ const int32_t high = fregisters_[reg + 1];
+ const int64_t value = Utils::LowHighTo64Bits(low, high);
+ return value;
+}
+
+
+double Simulator::get_fregister_double(FRegister reg) const {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ ASSERT((reg & 1) == 0);
+ const int64_t value = get_fregister_long(reg);
+ return bit_cast<double, int64_t>(value);
}
@@ -794,6 +842,26 @@
}
+double Simulator::ReadD(uword addr, Instr* instr) {
+ if ((addr & 7) == 0) {
+ double* ptr = reinterpret_cast<double*>(addr);
+ return *ptr;
+ }
+ UnalignedAccess("double-precision floating point read", addr, instr);
+ return 0.0;
+}
+
+
+void Simulator::WriteD(uword addr, double value, Instr* instr) {
+ if ((addr & 7) == 0) {
+ double* ptr = reinterpret_cast<double*>(addr);
+ *ptr = value;
+ return;
+ }
+ UnalignedAccess("double-precision floating point write", addr, instr);
+}
+
+
bool Simulator::OverflowFrom(int32_t alu_out,
int32_t left, int32_t right, bool addition) {
bool overflow;
@@ -905,7 +973,7 @@
set_register(RA, icount_);
// Zap floating point registers.
- double zap_dvalue = static_cast<double>(icount_);
+ int32_t zap_dvalue = icount_;
for (int i = F0; i <= F31; i++) {
set_fregister(static_cast<FRegister>(i), zap_dvalue);
}
@@ -1286,6 +1354,72 @@
}
+void Simulator::DecodeCop1(Instr* instr) {
+ ASSERT(instr->OpcodeField() == COP1);
+ if (instr->HasFormat()) {
+ // If the rs field is a valid format, then the function field identifies the
+ // instruction.
+ switch (instr->Cop1FunctionField()) {
+ case COP1_ADD: {
+ // Format(instr, "add.'fmt 'fd, 'fs, 'ft");
+ if (instr->FormatField() == FMT_S) {
+ float fs_val = get_fregister_float(instr->FsField());
+ float ft_val = get_fregister_float(instr->FtField());
+ set_fregister_float(instr->FdField(), fs_val + ft_val);
+ } else {
+ ASSERT(instr->FormatField() == FMT_D); // Only S and D supported.
+ double fs_val = get_fregister_double(instr->FsField());
+ double ft_val = get_fregister_double(instr->FtField());
+ set_fregister_double(instr->FdField(), fs_val + ft_val);
+ }
+ break;
+ }
+ case COP1_MOV: {
+ // Format(instr, "mov.'fmt 'fd, 'fs");
+ ASSERT(instr->FtField() == F0);
+ if (instr->FormatField() == FMT_S) {
+ float fs_val = get_fregister_float(instr->FsField());
+ set_fregister_float(instr->FdField(), fs_val);
+ } else {
+ ASSERT(instr->FormatField() == FMT_D);
+ double fs_val = get_fregister_double(instr->FsField());
+ set_fregister_double(instr->FdField(), fs_val);
+ }
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
+ UnimplementedInstruction(instr);
+ break;
+ }
+ }
+ } else {
+ // If the rs field isn't a valid format, then it must be a sub-op.
+ switch (instr->Cop1SubField()) {
+ case COP1_MF: {
+ // Format(instr, "mfc1 'rt, 'fs");
+ ASSERT(instr->Bits(0, 11) == 0);
+ int32_t fs_val = get_fregister(instr->FsField());
+ set_register(instr->RtField(), fs_val);
+ break;
+ }
+ case COP1_MT: {
+ // Format(instr, "mtc1 'rt, 'fs");
+ ASSERT(instr->Bits(0, 11) == 0);
+ int32_t rt_val = get_register(instr->RtField());
+ set_fregister(instr->FsField(), rt_val);
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
+ UnimplementedInstruction(instr);
+ break;
+ }
+ }
+ }
+}
+
+
void Simulator::InstructionDecode(Instr* instr) {
if (FLAG_trace_sim) {
const uword start = reinterpret_cast<uword>(instr);
@@ -1306,6 +1440,10 @@
DecodeRegImm(instr);
break;
}
+ case COP1: {
+ DecodeCop1(instr);
+ break;
+ }
case ADDIU: {
// Format(instr, "addiu 'rt, 'rs, 'imms");
int32_t rs_val = get_register(instr->RsField());
@@ -1403,6 +1541,19 @@
}
break;
}
+ case LDC1: {
+ // Format(instr, "ldc1 'ft, 'imms('rs)");
+ int32_t base_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ uword addr = base_val + imm_val;
+ if (Simulator::IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ double value = ReadD(addr, instr);
+ set_fregister_double(instr->FtField(), value);
+ }
+ break;
+ }
case LH: {
// Format(instr, "lh 'rt, 'imms('rs)");
int32_t base_val = get_register(instr->RsField());
@@ -1447,6 +1598,19 @@
}
break;
}
+ case LWC1: {
+ // Format(instr, "lwc1 'ft, 'imms('rs)");
+ int32_t base_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ uword addr = base_val + imm_val;
+ if (Simulator::IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ int32_t value = ReadW(addr, instr);
+ set_fregister(instr->FtField(), value);
+ }
+ break;
+ }
case ORI: {
// Format(instr, "ori 'rt, 'rs, 'immu");
int32_t rs_val = get_register(instr->RsField());
@@ -1466,6 +1630,19 @@
}
break;
}
+ case SDC1: {
+ // Format(instr, "sdc1 'ft, 'imms('rs)");
+ int32_t base_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ uword addr = base_val + imm_val;
+ if (Simulator::IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ double value = get_fregister_double(instr->FtField());
+ WriteD(addr, value, instr);
+ }
+ break;
+ }
case SH: {
// Format(instr, "sh 'rt, 'imms('rs)");
int32_t rt_val = get_register(instr->RtField());
@@ -1492,6 +1669,19 @@
}
break;
}
+ case SWC1: {
+ // Format(instr, "swc1 'ft, 'imms('rs)");
+ int32_t base_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ uword addr = base_val + imm_val;
+ if (Simulator::IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ int32_t value = get_fregister(instr->FtField());
+ WriteW(addr, value, instr);
+ }
+ break;
+ }
default: {
OS::PrintErr("Undecoded instruction: 0x%x at %p\n",
instr->InstructionBits(), instr);
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index f5695fb..a3bd6c7 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -39,8 +39,16 @@
int32_t get_register(Register reg) const;
// Accessors for floating point register state.
- void set_fregister(FRegister freg, double value);
- double get_fregister(FRegister) const;
+ void set_fregister(FRegister freg, int32_t value);
+ void set_fregister_float(FRegister freg, float value);
+ void set_fregister_double(FRegister freg, double value);
+ void set_fregister_long(FRegister freg, int64_t value);
+
+ int32_t get_fregister(FRegister freg) const;
+ float get_fregister_float(FRegister freg) const;
+ double get_fregister_double(FRegister freg) const;
+ int64_t get_fregister_long(FRegister freg) const;
+
// Accessor for the pc.
void set_pc(int32_t value) { pc_ = value; }
@@ -93,7 +101,7 @@
int32_t lo_reg_;
int32_t registers_[kNumberOfCpuRegisters];
- double fregisters_[kNumberOfFRegisters];
+ int32_t fregisters_[kNumberOfFRegisters];
uword pc_;
// Simulator support.
@@ -138,12 +146,16 @@
inline void WriteH(uword addr, uint16_t value, Instr* isntr);
inline void WriteW(uword addr, int value, Instr* instr);
+ inline double ReadD(uword addr, Instr* instr);
+ inline void WriteD(uword addr, double value, Instr* instr);
+
void DoBranch(Instr* instr, bool taken, bool likely);
void DoBreak(Instr *instr);
void DecodeSpecial(Instr* instr);
void DecodeSpecial2(Instr* instr);
void DecodeRegImm(Instr* instr);
+ void DecodeCop1(Instr* instr);
void InstructionDecode(Instr* instr);
void Execute();
diff --git a/runtime/vm/token.h b/runtime/vm/token.h
index daf8cea..c568ddd 100644
--- a/runtime/vm/token.h
+++ b/runtime/vm/token.h
@@ -170,6 +170,7 @@
KW(kNULL, "null", 0, kKeyword) \
KW(kOPERATOR, "operator", 0, kPseudoKeyword) \
KW(kPART, "part", 0, kPseudoKeyword) \
+ KW(kRETHROW, "rethrow", 0, kKeyword) \
KW(kRETURN, "return", 0, kKeyword) \
KW(kSET, "set", 0, kPseudoKeyword) \
KW(kSTATIC, "static", 0, kPseudoKeyword) \
diff --git a/tests/language/if_conversion_vm_test.dart b/tests/language/if_conversion_vm_test.dart
index 22e6203..3ed12a1 100644
--- a/tests/language/if_conversion_vm_test.dart
+++ b/tests/language/if_conversion_vm_test.dart
@@ -30,6 +30,15 @@
bigPower(i) => (i == 11) ? 0 : POWER_OF_2;
+cse(i) {
+ final a = i == 0 ? 0 : 1;
+ final b = i == 0 ? 2 : 3;
+ return a + b;
+}
+
+f17(b) => b ? 0 : 11;
+f18(b) => b ? 2 : 0;
+
main() {
for (var i = 0; i < 10000; i++) {
f1(i);
@@ -48,7 +57,10 @@
f14(i);
f15(i);
f16(i);
+ cse(i);
bigPower(i);
+ f17(true);
+ f18(true);
}
Expect.equals(0, f1(0));
@@ -89,4 +101,13 @@
Expect.equals(0, bigPower(11));
Expect.equals(POWER_OF_2, bigPower(12));
+
+ Expect.equals(2, cse(0));
+ Expect.equals(4, cse(1));
+
+ Expect.equals(11, f17(false));
+ Expect.equals(0, f17(true));
+
+ Expect.equals(0, f18(false));
+ Expect.equals(2, f18(true));
}
\ No newline at end of file
diff --git a/tests/language/language.status b/tests/language/language.status
index 13347e4..f732024 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -555,6 +555,8 @@
[ $compiler == dart2dart && $minified ]
+rethrow_test: Fail
+
# TODO(tball): Assign proper bug numbers.
class_literal_test/none: Fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 10d7d8d..ff16206 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -133,6 +133,7 @@
constructor_negative_test: Pass # Wrong reason: the expression 'C()' is valid with class literals.
throw_expr_test: Fail
+rethrow_test: Fail
metadata_test: Fail # Metadata on type parameters not supported.
infinity_test: Fail # Issue 4984
positive_bit_operations_test: Fail # (floitsch): This will be fixed when dart2js uses unsigned input for >>.
diff --git a/tests/language/rethrow_test.dart b/tests/language/rethrow_test.dart
index 7c3bf04..4b535c9 100644
--- a/tests/language/rethrow_test.dart
+++ b/tests/language/rethrow_test.dart
@@ -29,7 +29,7 @@
Expect.fail("Should have thrown an exception");
} catch (e) {
Expect.equals(true, identical(e, currentException));
- throw;
+ rethrow;
Expect.fail("Should have thrown an exception");
}
} on OtherException catch (e) {
@@ -47,7 +47,7 @@
Expect.fail("Should have thrown an exception");
} catch (e) {
Expect.equals(true, identical(e, currentException));
- throw;
+ rethrow;
Expect.fail("Should have thrown an exception");
}
} catch (e) {
diff --git a/tools/VERSION b/tools/VERSION
index e4e6452..971672e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 4
BUILD 6
-PATCH 0
+PATCH 1
diff --git a/tools/dom/scripts/fremontcutbuilder.py b/tools/dom/scripts/fremontcutbuilder.py
index c0919fb..bb82b26 100755
--- a/tools/dom/scripts/fremontcutbuilder.py
+++ b/tools/dom/scripts/fremontcutbuilder.py
@@ -148,36 +148,6 @@
def main(parallel=False):
current_dir = os.path.dirname(__file__)
- webkit_dirs = [
- 'css',
- 'dom',
- 'fileapi',
- 'html',
- 'html/canvas',
- 'inspector',
- 'loader',
- 'loader/appcache',
- 'Modules/battery',
- 'Modules/filesystem',
- 'Modules/gamepad',
- 'Modules/geolocation',
- 'Modules/indexeddb',
- 'Modules/mediasource',
- 'Modules/mediastream',
- 'Modules/notifications',
- 'Modules/quota',
- 'Modules/speech',
- 'Modules/webaudio',
- 'Modules/webdatabase',
- 'Modules/websockets',
- 'page',
- 'plugins',
- 'storage',
- 'svg',
- 'workers',
- 'xml',
- ]
-
ignored_idls = [
'AbstractView.idl',
]
@@ -190,15 +160,15 @@
raise RuntimeError('directory not found: %s' % webcore_dir)
def visitor(arg, dir_name, names):
+ if os.path.basename(dir_name) in ['bindings', 'testing']:
+ names[:] = [] # Do not go underneath
for name in names:
file_name = os.path.join(dir_name, name)
(interface, ext) = os.path.splitext(file_name)
if ext == '.idl' and name not in ignored_idls:
idl_files.append(file_name)
- for dir_name in webkit_dirs:
- dir_path = os.path.join(webcore_dir, dir_name)
- os.path.walk(dir_path, visitor, None)
+ os.path.walk(webcore_dir, visitor, webcore_dir)
database_dir = os.path.join(current_dir, '..', 'database')
return build_database(idl_files, database_dir, parallel=parallel)