Version 1.10.0-dev.1.7
svn merge -c 45139 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 45182 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 45215 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 45223 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 45253 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 45254 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: https://dart.googlecode.com/svn/trunk@45268 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/dart/runtime/lib/bigint.dart b/dart/runtime/lib/bigint.dart
index 78b5cc5..f4ff408 100644
--- a/dart/runtime/lib/bigint.dart
+++ b/dart/runtime/lib/bigint.dart
@@ -1042,10 +1042,13 @@
if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) {
assert(i == r_used);
r_digits[r_used++] = 1; // Quotient = 1.
- r_digits[r_used] = 0; // Leading zero.
// Subtract divisor from remainder.
_absSub(r_digits, r_used, t_digits, t_used, r_digits);
+ } else {
+ // Account for possible carry in _mulAdd step.
+ r_digits[r_used++] = 0;
}
+ r_digits[r_used] = 0; // Leading zero for 64-bit processing.
// Negate y so we can later use _mulAdd instead of non-existent _mulSub.
var ny_digits = new Uint32List(y_used + 2);
ny_digits[y_used] = 1;
@@ -1137,10 +1140,13 @@
if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) {
assert(i == r_used);
r_digits[r_used++] = 1; // Quotient = 1.
- r_digits[r_used] = 0; // Leading zero.
// Subtract divisor from remainder.
_absSub(r_digits, r_used, t_digits, t_used, r_digits);
+ } else {
+ // Account for possible carry in _mulAdd step.
+ r_digits[r_used++] = 0;
}
+ r_digits[r_used] = 0; // Leading zero for 64-bit processing.
// Negated y_digits passed in ny_digits allow the use of _mulAdd instead of
// unimplemented _mulSub.
// ny_digits is read-only and has y_used digits (possibly including several
diff --git a/dart/runtime/observatory/lib/app.dart b/dart/runtime/observatory/lib/app.dart
index 6b0a4e1..9bb2df8 100644
--- a/dart/runtime/observatory/lib/app.dart
+++ b/dart/runtime/observatory/lib/app.dart
@@ -15,6 +15,7 @@
import 'package:observatory/tracer.dart';
import 'package:observatory/utils.dart';
import 'package:polymer/polymer.dart';
+import 'package:usage/usage_html.dart';
export 'package:observatory/utils.dart';
@@ -25,3 +26,4 @@
part 'src/app/settings.dart';
part 'src/app/target_manager.dart';
part 'src/app/view_model.dart';
+part 'src/app/analytics.dart';
diff --git a/dart/runtime/observatory/lib/src/app/analytics.dart b/dart/runtime/observatory/lib/src/app/analytics.dart
new file mode 100644
index 0000000..fd04156
--- /dev/null
+++ b/dart/runtime/observatory/lib/src/app/analytics.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2015, 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.
+
+part of app;
+
+class Analytics {
+ static final _UA = 'UA-26406144-17';
+ static final _name = 'Observatory';
+ static final _version = '1.10';
+ static final _googleAnalytics = new AnalyticsHtml(_UA, _name, _version);
+
+ static initialize() {
+ // We only send screen views. This is allowed without user permission.
+ // Note, before flipping this to be true we need a UI to allow users to
+ // control this.
+ _googleAnalytics.optIn = false;
+ }
+
+ /// Called whenever an Observatory page is viewed.
+ static Future reportPageView(Uri uri) {
+ // The screen name is the uri's path. e.g. inspect, profile.
+ final screenName = uri.path;
+ return _googleAnalytics.sendScreenView(screenName);
+ }
+}
diff --git a/dart/runtime/observatory/lib/src/app/application.dart b/dart/runtime/observatory/lib/src/app/application.dart
index 090d300..d87d6fb 100644
--- a/dart/runtime/observatory/lib/src/app/application.dart
+++ b/dart/runtime/observatory/lib/src/app/application.dart
@@ -46,6 +46,7 @@
assert(app == null);
app = this;
_registerPages();
+ Analytics.initialize();
locationManager._init(this);
}
diff --git a/dart/runtime/observatory/lib/src/app/page.dart b/dart/runtime/observatory/lib/src/app/page.dart
index e79f3dc..858e75f 100644
--- a/dart/runtime/observatory/lib/src/app/page.dart
+++ b/dart/runtime/observatory/lib/src/app/page.dart
@@ -27,9 +27,9 @@
}
/// Called when the page should update its state based on [uri].
- /// NOTE: Only called when the page is installed.
void visit(Uri uri, Map argsMap) {
args = toObservable(argsMap);
+ Analytics.reportPageView(uri);
_visit(uri);
}
diff --git a/dart/runtime/observatory/observatory_sources.gypi b/dart/runtime/observatory/observatory_sources.gypi
index d16cbd8..fadca29 100644
--- a/dart/runtime/observatory/observatory_sources.gypi
+++ b/dart/runtime/observatory/observatory_sources.gypi
@@ -17,6 +17,7 @@
'lib/service_common.dart',
'lib/service_io.dart',
'lib/service_html.dart',
+ 'lib/src/app/analytics.dart',
'lib/src/app/application.dart',
'lib/src/app/chart.dart',
'lib/src/app/location_manager.dart',
diff --git a/dart/runtime/vm/assembler_ia32.cc b/dart/runtime/vm/assembler_ia32.cc
index c060bbf..d876feb 100644
--- a/dart/runtime/vm/assembler_ia32.cc
+++ b/dart/runtime/vm/assembler_ia32.cc
@@ -1771,8 +1771,9 @@
}
-void Assembler::shldl(Register dst, Register src) {
+void Assembler::shldl(Register dst, Register src, Register shifter) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ ASSERT(shifter == ECX);
EmitUint8(0x0F);
EmitUint8(0xA5);
EmitRegisterOperand(src, dst);
@@ -1789,16 +1790,18 @@
}
-void Assembler::shldl(const Address& operand, Register src) {
+void Assembler::shldl(const Address& operand, Register src, Register shifter) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ ASSERT(shifter == ECX);
EmitUint8(0x0F);
EmitUint8(0xA5);
EmitOperand(src, Operand(operand));
}
-void Assembler::shrdl(Register dst, Register src) {
+void Assembler::shrdl(Register dst, Register src, Register shifter) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ ASSERT(shifter == ECX);
EmitUint8(0x0F);
EmitUint8(0xAD);
EmitRegisterOperand(src, dst);
@@ -1815,8 +1818,9 @@
}
-void Assembler::shrdl(const Address& dst, Register src) {
+void Assembler::shrdl(const Address& dst, Register src, Register shifter) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ ASSERT(shifter == ECX);
EmitUint8(0x0F);
EmitUint8(0xAD);
EmitOperand(src, Operand(dst));
diff --git a/dart/runtime/vm/assembler_ia32.h b/dart/runtime/vm/assembler_ia32.h
index a0d03de..edf7634 100644
--- a/dart/runtime/vm/assembler_ia32.h
+++ b/dart/runtime/vm/assembler_ia32.h
@@ -603,12 +603,12 @@
void sarl(Register reg, const Immediate& imm);
void sarl(Register operand, Register shifter);
void sarl(const Address& address, Register shifter);
- void shldl(Register dst, Register src);
+ void shldl(Register dst, Register src, Register shifter);
void shldl(Register dst, Register src, const Immediate& imm);
- void shldl(const Address& operand, Register src);
- void shrdl(Register dst, Register src);
+ void shldl(const Address& operand, Register src, Register shifter);
+ void shrdl(Register dst, Register src, Register shifter);
void shrdl(Register dst, Register src, const Immediate& imm);
- void shrdl(const Address& dst, Register src);
+ void shrdl(const Address& dst, Register src, Register shifter);
void negl(Register reg);
void notl(Register reg);
diff --git a/dart/runtime/vm/assembler_ia32_test.cc b/dart/runtime/vm/assembler_ia32_test.cc
index 6492625..2fd2866 100644
--- a/dart/runtime/vm/assembler_ia32_test.cc
+++ b/dart/runtime/vm/assembler_ia32_test.cc
@@ -579,7 +579,7 @@
__ movl(EAX, Immediate(0));
__ movl(ECX, Immediate(3));
__ sarl(Address(ESP, 0), ECX);
- __ shrdl(Address(ESP, 0), EAX);
+ __ shrdl(Address(ESP, 0), EAX, ECX);
__ cmpl(Address(ESP, 0), Immediate(0x1e000000));
__ j(EQUAL, &donetest14);
__ int3();
@@ -592,7 +592,7 @@
__ movl(EAX, Immediate(-1));
__ movl(ECX, Immediate(2));
__ shll(Address(ESP, 0), ECX);
- __ shldl(Address(ESP, 0), EAX);
+ __ shldl(Address(ESP, 0), EAX, ECX);
__ cmpl(Address(ESP, 0), Immediate(0xF0000003));
__ j(EQUAL, &donetest15);
__ int3();
diff --git a/dart/runtime/vm/assembler_x64.cc b/dart/runtime/vm/assembler_x64.cc
index 7b2d914..410d43b 100644
--- a/dart/runtime/vm/assembler_x64.cc
+++ b/dart/runtime/vm/assembler_x64.cc
@@ -2248,11 +2248,11 @@
void Assembler::shldl(Register dst, Register src, const Immediate& imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
ASSERT(imm.is_int8());
- Operand operand(src);
- EmitOperandREX(dst, operand, REX_NONE);
+ Operand operand(dst);
+ EmitOperandREX(src, operand, REX_NONE);
EmitUint8(0x0F);
EmitUint8(0xA4);
- EmitOperand(src & 7, Operand(dst));
+ EmitOperand(src & 7, operand);
EmitUint8(imm.value() & 0xFF);
}
@@ -2290,11 +2290,11 @@
void Assembler::shldq(Register dst, Register src, const Immediate& imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
ASSERT(imm.is_int8());
- Operand operand(src);
- EmitOperandREX(dst, operand, REX_W);
+ Operand operand(dst);
+ EmitOperandREX(src, operand, REX_W);
EmitUint8(0x0F);
EmitUint8(0xA4);
- EmitOperand(src & 7, Operand(dst));
+ EmitOperand(src & 7, operand);
EmitUint8(imm.value() & 0xFF);
}
@@ -2302,22 +2302,22 @@
void Assembler::shldq(Register dst, Register src, Register shifter) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
ASSERT(shifter == RCX);
- Operand operand(src);
- EmitOperandREX(dst, operand, REX_W);
+ Operand operand(dst);
+ EmitOperandREX(src, operand, REX_W);
EmitUint8(0x0F);
EmitUint8(0xA5);
- EmitOperand(src & 7, Operand(dst));
+ EmitOperand(src & 7, operand);
}
void Assembler::shrdq(Register dst, Register src, Register shifter) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
ASSERT(shifter == RCX);
- Operand operand(src);
- EmitOperandREX(dst, operand, REX_W);
+ Operand operand(dst);
+ EmitOperandREX(src, operand, REX_W);
EmitUint8(0x0F);
EmitUint8(0xAD);
- EmitOperand(src & 7, Operand(dst));
+ EmitOperand(src & 7, operand);
}
diff --git a/dart/runtime/vm/assembler_x64_test.cc b/dart/runtime/vm/assembler_x64_test.cc
index 85ee637..9989e3b 100644
--- a/dart/runtime/vm/assembler_x64_test.cc
+++ b/dart/runtime/vm/assembler_x64_test.cc
@@ -1360,10 +1360,10 @@
const int32_t right = 0xffffffff;
const int32_t shifted = 0xf0000003;
__ movl(RDX, Immediate(left));
- __ movl(RAX, Immediate(right));
+ __ movl(R8, Immediate(right));
__ movl(RCX, Immediate(2));
__ shll(RDX, RCX); // RDX = 0xff000000 << 2 == 0xfc000000
- __ shldl(RDX, RAX, Immediate(2));
+ __ shldl(RDX, R8, Immediate(2));
// RDX = high32(0xfc000000:0xffffffff << 2) == 0xf0000003
__ cmpl(RDX, Immediate(shifted));
__ j(EQUAL, &donetest15a);
@@ -1377,10 +1377,10 @@
const int64_t right = 0xffffffffffffffff;
const int64_t shifted = 0xf000000000000003;
__ movq(RDX, Immediate(left));
- __ movq(RAX, Immediate(right));
+ __ movq(R8, Immediate(right));
__ movq(RCX, Immediate(2));
__ shlq(RDX, RCX); // RDX = 0xff00000000000000 << 2 == 0xfc00000000000000
- __ shldq(RDX, RAX, Immediate(2));
+ __ shldq(RDX, R8, Immediate(2));
// RDX = high64(0xfc00000000000000:0xffffffffffffffff << 2)
// == 0xf000000000000003
__ cmpq(RDX, Immediate(shifted));
@@ -1395,10 +1395,10 @@
const int64_t right = 0xffffffffffffffff;
const int64_t shifted = 0xf000000000000003;
__ movq(RDX, Immediate(left));
- __ movq(RAX, Immediate(right));
+ __ movq(R8, Immediate(right));
__ movq(RCX, Immediate(2));
__ shlq(RDX, RCX); // RDX = 0xff00000000000000 << 2 == 0xfc00000000000000
- __ shldq(RDX, RAX, RCX);
+ __ shldq(RDX, R8, RCX);
// RDX = high64(0xfc00000000000000:0xffffffffffffffff << 2)
// == 0xf000000000000003
__ cmpq(RDX, Immediate(shifted));
@@ -1413,10 +1413,10 @@
const int64_t right = 0xffffffffffffffff;
const int64_t shifted = 0xcff0000000000000;
__ movq(RDX, Immediate(left));
- __ movq(RAX, Immediate(right));
+ __ movq(R8, Immediate(right));
__ movq(RCX, Immediate(2));
__ shrq(RDX, RCX); // RDX = 0xff00000000000000 >> 2 == 0x3fc0000000000000
- __ shrdq(RDX, RAX, RCX);
+ __ shrdq(RDX, R8, RCX);
// RDX = low64(0xffffffffffffffff:0x3fc0000000000000 >> 2)
// == 0xcff0000000000000
__ cmpq(RDX, Immediate(shifted));
diff --git a/dart/runtime/vm/code_generator.cc b/dart/runtime/vm/code_generator.cc
index aa4671f..755cc40 100644
--- a/dart/runtime/vm/code_generator.cc
+++ b/dart/runtime/vm/code_generator.cc
@@ -113,7 +113,7 @@
Exceptions::ThrowArgumentError(error);
}
const intptr_t len = Smi::Cast(length).Value();
- if (len < 0) {
+ if ((len < 0) || (len > Array::kMaxElements)) {
const String& error = String::Handle(String::NewFormatted(
"Length (%" Pd ") must be an integer in the range [0..%" Pd "].",
len, Array::kMaxElements));
diff --git a/dart/runtime/vm/intermediate_language_ia32.cc b/dart/runtime/vm/intermediate_language_ia32.cc
index 6d70aa4..5ea1fa2 100644
--- a/dart/runtime/vm/intermediate_language_ia32.cc
+++ b/dart/runtime/vm/intermediate_language_ia32.cc
@@ -6171,7 +6171,7 @@
__ cmpl(ECX, Immediate(31));
__ j(ABOVE, &large_shift);
- __ shrdl(left_lo, left_hi); // Shift count in CL.
+ __ shrdl(left_lo, left_hi, ECX); // Shift count in CL.
__ sarl(left_hi, ECX); // Shift count in CL.
__ jmp(&done, Assembler::kNearJump);
@@ -6190,7 +6190,7 @@
__ cmpl(ECX, Immediate(31));
__ j(ABOVE, &large_shift);
- __ shldl(left_hi, left_lo); // Shift count in CL.
+ __ shldl(left_hi, left_lo, ECX); // Shift count in CL.
__ shll(left_lo, ECX); // Shift count in CL.
// Check for overflow by shifting back the high 32 bits
// and comparing with the input.
@@ -6221,7 +6221,7 @@
__ cmpl(ECX, Immediate(31));
__ j(ABOVE, &large_shift);
- __ shldl(left_hi, left_lo); // Shift count in CL.
+ __ shldl(left_hi, left_lo, ECX); // Shift count in CL.
__ shll(left_lo, ECX); // Shift count in CL.
__ jmp(&done, Assembler::kNearJump);
diff --git a/dart/runtime/vm/intrinsifier_arm.cc b/dart/runtime/vm/intrinsifier_arm.cc
index 5705f29..ffd6655 100644
--- a/dart/runtime/vm/intrinsifier_arm.cc
+++ b/dart/runtime/vm/intrinsifier_arm.cc
@@ -20,6 +20,13 @@
DECLARE_FLAG(bool, enable_type_checks);
+// When entering intrinsics code:
+// R5: IC Data
+// R4: Arguments descriptor
+// LR: Return address
+// The R5, R4 registers can be destroyed only if there is no slow-path, i.e.
+// if the intrinsified method always executes a return.
+// The FP register should not be modified, because it is used by the profiler.
#define __ assembler->
diff --git a/dart/runtime/vm/intrinsifier_arm64.cc b/dart/runtime/vm/intrinsifier_arm64.cc
index baf7a66..402c262 100644
--- a/dart/runtime/vm/intrinsifier_arm64.cc
+++ b/dart/runtime/vm/intrinsifier_arm64.cc
@@ -19,6 +19,13 @@
DECLARE_FLAG(bool, enable_type_checks);
+// When entering intrinsics code:
+// R5: IC Data
+// R4: Arguments descriptor
+// LR: Return address
+// The R5, R4 registers can be destroyed only if there is no slow-path, i.e.
+// if the intrinsified method always executes a return.
+// The FP register should not be modified, because it is used by the profiler.
#define __ assembler->
diff --git a/dart/runtime/vm/intrinsifier_ia32.cc b/dart/runtime/vm/intrinsifier_ia32.cc
index a73612d..66ea7d0 100644
--- a/dart/runtime/vm/intrinsifier_ia32.cc
+++ b/dart/runtime/vm/intrinsifier_ia32.cc
@@ -26,6 +26,13 @@
DECLARE_FLAG(bool, enable_type_checks);
+// When entering intrinsics code:
+// ECX: IC Data
+// EDX: Arguments descriptor
+// TOS: Return address
+// The ECX, EDX registers can be destroyed only if there is no slow-path, i.e.
+// if the intrinsified method always executes a return.
+// The EBP register should not be modified, because it is used by the profiler.
#define __ assembler->
@@ -572,7 +579,7 @@
__ movl(EAX, EBX);
__ shll(EBX, ECX);
__ xorl(EDI, EDI);
- __ shldl(EDI, EAX);
+ __ shldl(EDI, EAX, ECX);
// Result in EDI (high) and EBX (low).
const Class& mint_class = Class::Handle(
Isolate::Current()->object_store()->mint_class());
@@ -806,12 +813,80 @@
void Intrinsifier::Bigint_lsh(Assembler* assembler) {
- // TODO(regis): Implement.
+ // static void _lsh(Uint32List x_digits, int x_used, int n,
+ // Uint32List r_digits)
+
+ __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits
+ __ movl(ECX, Address(ESP, 2 * kWordSize)); // n is Smi
+ __ SmiUntag(ECX);
+ __ movl(EBX, Address(ESP, 1 * kWordSize)); // r_digits
+ __ movl(ESI, ECX);
+ __ sarl(ESI, Immediate(5)); // ESI = n ~/ _DIGIT_BITS.
+ __ leal(EBX, FieldAddress(EBX, ESI, TIMES_4, TypedData::data_offset()));
+ __ movl(ESI, Address(ESP, 3 * kWordSize)); // x_used > 0, Smi.
+ __ SmiUntag(ESI);
+ __ decl(ESI);
+ __ xorl(EAX, EAX); // EAX = 0.
+ __ movl(EDX, FieldAddress(EDI, ESI, TIMES_4, TypedData::data_offset()));
+ __ shldl(EAX, EDX, ECX);
+ __ movl(Address(EBX, ESI, TIMES_4, Bigint::kBytesPerDigit), EAX);
+ Label last;
+ __ cmpl(ESI, Immediate(0));
+ __ j(EQUAL, &last, Assembler::kNearJump);
+ Label loop;
+ __ Bind(&loop);
+ __ movl(EAX, EDX);
+ __ movl(EDX,
+ FieldAddress(EDI, ESI, TIMES_4,
+ TypedData::data_offset() - Bigint::kBytesPerDigit));
+ __ shldl(EAX, EDX, ECX);
+ __ movl(Address(EBX, ESI, TIMES_4, 0), EAX);
+ __ decl(ESI);
+ __ j(NOT_ZERO, &loop, Assembler::kNearJump);
+ __ Bind(&last);
+ __ shldl(EDX, ESI, ECX); // ESI == 0.
+ __ movl(Address(EBX, 0), EDX);
+ // Returning Object::null() is not required, since this method is private.
+ __ ret();
}
void Intrinsifier::Bigint_rsh(Assembler* assembler) {
- // TODO(regis): Implement.
+ // static void _rsh(Uint32List x_digits, int x_used, int n,
+ // Uint32List r_digits)
+
+ __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits
+ __ movl(ECX, Address(ESP, 2 * kWordSize)); // n is Smi
+ __ SmiUntag(ECX);
+ __ movl(EBX, Address(ESP, 1 * kWordSize)); // r_digits
+ __ movl(EDX, ECX);
+ __ sarl(EDX, Immediate(5)); // EDX = n ~/ _DIGIT_BITS.
+ __ movl(ESI, Address(ESP, 3 * kWordSize)); // x_used > 0, Smi.
+ __ SmiUntag(ESI);
+ __ decl(ESI);
+ // EDI = &x_digits[x_used - 1].
+ __ leal(EDI, FieldAddress(EDI, ESI, TIMES_4, TypedData::data_offset()));
+ __ subl(ESI, EDX);
+ // EBX = &r_digits[x_used - 1 - (n ~/ 32)].
+ __ leal(EBX, FieldAddress(EBX, ESI, TIMES_4, TypedData::data_offset()));
+ __ negl(ESI);
+ __ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
+ Label last;
+ __ cmpl(ESI, Immediate(0));
+ __ j(EQUAL, &last, Assembler::kNearJump);
+ Label loop;
+ __ Bind(&loop);
+ __ movl(EAX, EDX);
+ __ movl(EDX, Address(EDI, ESI, TIMES_4, Bigint::kBytesPerDigit));
+ __ shrdl(EAX, EDX, ECX);
+ __ movl(Address(EBX, ESI, TIMES_4, 0), EAX);
+ __ incl(ESI);
+ __ j(NOT_ZERO, &loop, Assembler::kNearJump);
+ __ Bind(&last);
+ __ shrdl(EDX, ESI, ECX); // ESI == 0.
+ __ movl(Address(EBX, 0), EDX);
+ // Returning Object::null() is not required, since this method is private.
+ __ ret();
}
diff --git a/dart/runtime/vm/intrinsifier_mips.cc b/dart/runtime/vm/intrinsifier_mips.cc
index 63c7ac0..54a63c0 100644
--- a/dart/runtime/vm/intrinsifier_mips.cc
+++ b/dart/runtime/vm/intrinsifier_mips.cc
@@ -19,6 +19,14 @@
DECLARE_FLAG(bool, enable_type_checks);
+// When entering intrinsics code:
+// S5: IC Data
+// S4: Arguments descriptor
+// RA: Return address
+// The S5, S4 registers can be destroyed only if there is no slow-path, i.e.
+// if the intrinsified method always executes a return.
+// The FP register should not be modified, because it is used by the profiler.
+
#define __ assembler->
diff --git a/dart/runtime/vm/intrinsifier_x64.cc b/dart/runtime/vm/intrinsifier_x64.cc
index 9a5baf3..d34759f 100644
--- a/dart/runtime/vm/intrinsifier_x64.cc
+++ b/dart/runtime/vm/intrinsifier_x64.cc
@@ -23,8 +23,9 @@
// RBX: IC Data
// R10: Arguments descriptor
// TOS: Return address
-// The RBX, R10 registers can be destroyed only if there is no slow-path (i.e.,
-// the methods returns true).
+// The RBX, R10 registers can be destroyed only if there is no slow-path, i.e.
+// if the intrinsified method always executes a return.
+// The RBP register should not be modified, because it is used by the profiler.
#define __ assembler->
@@ -757,8 +758,7 @@
__ decq(R8);
__ j(NOT_ZERO, &loop, Assembler::kNearJump);
__ Bind(&last);
- __ xorq(RAX, RAX); // RAX = 0.
- __ shldq(RDX, RAX, RCX);
+ __ shldq(RDX, R8, RCX); // R8 == 0.
__ movq(Address(RBX, 0), RDX);
// Returning Object::null() is not required, since this method is private.
__ ret();
@@ -770,34 +770,33 @@
// Uint32List r_digits)
__ movq(RDI, Address(RSP, 4 * kWordSize)); // x_digits
- __ movq(R8, Address(RSP, 3 * kWordSize)); // x_used is Smi
- __ subq(R8, Immediate(2)); // x_used > 0, Smi. R8 = x_used - 1, round up.
- __ sarq(R8, Immediate(2));
__ movq(RCX, Address(RSP, 2 * kWordSize)); // n is Smi
__ SmiUntag(RCX);
__ movq(RBX, Address(RSP, 1 * kWordSize)); // r_digits
- __ movq(RSI, RCX);
- __ sarq(RSI, Immediate(6)); // RSI = n ~/ (2*_DIGIT_BITS).
+ __ movq(RDX, RCX);
+ __ sarq(RDX, Immediate(6)); // RDX = n ~/ (2*_DIGIT_BITS).
+ __ movq(RSI, Address(RSP, 3 * kWordSize)); // x_used is Smi
+ __ subq(RSI, Immediate(2)); // x_used > 0, Smi. RSI = x_used - 1, round up.
+ __ sarq(RSI, Immediate(2));
__ leaq(RDI, FieldAddress(RDI, RSI, TIMES_8, TypedData::data_offset()));
- __ movq(RDX, Address(RDI, 0));
- __ subq(R8, RSI); // R8 + 1 = number of digit pairs to read.
+ __ subq(RSI, RDX); // RSI + 1 = number of digit pairs to read.
+ __ leaq(RBX, FieldAddress(RBX, RSI, TIMES_8, TypedData::data_offset()));
+ __ negq(RSI);
+ __ movq(RDX, Address(RDI, RSI, TIMES_8, 0));
Label last;
- __ cmpq(R8, Immediate(0));
+ __ cmpq(RSI, Immediate(0));
__ j(EQUAL, &last, Assembler::kNearJump);
- __ xorq(R9, R9); // R9 = 0.
Label loop;
__ Bind(&loop);
__ movq(RAX, RDX);
- __ movq(RDX, Address(RDI, R9, TIMES_8, 2 * Bigint::kBytesPerDigit));
+ __ movq(RDX, Address(RDI, RSI, TIMES_8, 2 * Bigint::kBytesPerDigit));
__ shrdq(RAX, RDX, RCX);
- __ movq(FieldAddress(RBX, R9, TIMES_8, TypedData::data_offset()), RAX);
- __ incq(R9);
- __ cmpq(R9, R8);
- __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
+ __ movq(Address(RBX, RSI, TIMES_8, 0), RAX);
+ __ incq(RSI);
+ __ j(NOT_ZERO, &loop, Assembler::kNearJump);
__ Bind(&last);
- __ xorq(RAX, RAX); // RAX = 0.
- __ shrdq(RDX, RAX, RCX);
- __ movq(FieldAddress(RBX, R8, TIMES_8, TypedData::data_offset()), RDX);
+ __ shrdq(RDX, RSI, RCX); // RSI == 0.
+ __ movq(Address(RBX, 0), RDX);
// Returning Object::null() is not required, since this method is private.
__ ret();
}
@@ -1782,7 +1781,7 @@
const intptr_t kStartIndexOffset = 2 * kWordSize;
const intptr_t kEndIndexOffset = 1 * kWordSize;
Label fall_through, ok;
- __ movq(RSI, Address(RSP, + kEndIndexOffset));
+ __ movq(RSI, Address(RSP, + kStartIndexOffset));
__ movq(RDI, Address(RSP, + kEndIndexOffset));
__ orq(RSI, RDI);
__ testq(RSI, Immediate(kSmiTagMask));
diff --git a/dart/runtime/vm/object_test.cc b/dart/runtime/vm/object_test.cc
index 7b23600..4da8d3c 100644
--- a/dart/runtime/vm/object_test.cc
+++ b/dart/runtime/vm/object_test.cc
@@ -1951,6 +1951,27 @@
}
+TEST_CASE(ArrayLength) {
+ const intptr_t kLength = Array::kMaxElements + 1;
+ ASSERT(kLength >= 0);
+ char buffer[1024];
+ OS::SNPrint(buffer, sizeof(buffer),
+ "main() {\n"
+ " new List(%" Pd ");\n"
+ "}\n",
+ kLength);
+ Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
+ EXPECT_VALID(lib);
+ Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+ OS::SNPrint(buffer, sizeof(buffer),
+ "Unhandled exception:\n"
+ "Invalid argument(s): Length (%" Pd ") must be an integer "
+ "in the range [0..%" Pd "].",
+ kLength, Array::kMaxElements);
+ EXPECT_ERROR(result, buffer);
+}
+
+
TEST_CASE(StringCodePointIterator) {
const String& str0 = String::Handle(String::New(""));
String::CodePointIterator it0(str0);
diff --git a/dart/tests/language/vm/regress_23238_test.dart b/dart/tests/language/vm/regress_23238_test.dart
new file mode 100644
index 0000000..88250b2
--- /dev/null
+++ b/dart/tests/language/vm/regress_23238_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2015, 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";
+
+void main() {
+ int x = 327680;
+ int r = 65536;
+ for (var i = 0; i < 200; i++) {
+ Expect.equals(r, x ~/ 5);
+ x *= 10;
+ r *= 10;
+ }
+}
diff --git a/dart/tools/VERSION b/dart/tools/VERSION
index 30df61a..518e69f 100644
--- a/dart/tools/VERSION
+++ b/dart/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 10
PATCH 0
PRERELEASE 1
-PRERELEASE_PATCH 6
+PRERELEASE_PATCH 7