Merge
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 6868b86..7e94a3d 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -533,13 +533,23 @@
 8f5ca46a90af013525cbdf3b023727450cdb8119 jdk8u72-b13
 6cbd347daa9367b78e385f2e8eba222a30b3bea1 jdk8u72-b14
 fff0c11d2811deb70bef213d6d8478b3e3796658 jdk8u72-b15
+928374287059bb10b87dade1c2d984f8c4df01b3 jdk8u72-b31
 443abbc4e048b13e075486a86ddafca520257fdf jdk8u73-b00
 fc0ed68cbc5cbdb2efdb75f3309b5de2a64f5a57 jdk8u73-b01
 6aacbee7e4c84a30761faf58a682b07b8bdf54da jdk8u73-b02
 87614decb34cd6076f136b6d51be83f13e3e6aed jdk8u74-b00
 33b310c85259e0d7ed112ab2e01008228e263371 jdk8u74-b01
 bee679b986f51fe4d65d6df11fea93d1543b6502 jdk8u74-b02
+fd813938f2dd5f8e9d7caa2c1628af6da6683831 jdk8u74-b31
+9d7c49d756f01acbcbe8d0d3c5d5d4e92a7cf119 jdk8u74-b32
 928374287059bb10b87dade1c2d984f8c4df01b3 jdk8u72-b31
+443abbc4e048b13e075486a86ddafca520257fdf jdk8u73-b00
+fc0ed68cbc5cbdb2efdb75f3309b5de2a64f5a57 jdk8u73-b01
+6aacbee7e4c84a30761faf58a682b07b8bdf54da jdk8u73-b02
+87614decb34cd6076f136b6d51be83f13e3e6aed jdk8u74-b00
+33b310c85259e0d7ed112ab2e01008228e263371 jdk8u74-b01
+bee679b986f51fe4d65d6df11fea93d1543b6502 jdk8u74-b02
+fd813938f2dd5f8e9d7caa2c1628af6da6683831 jdk8u74-b31
 ac4e9dfd23236821432786b27566fa2f800aa3d4 jdk8u75-b00
 d63a77fb06149b75dbb043a175a9c4a906ac26ef jdk8u75-b01
 320f984ac52b56da66aff581a2c4830eadc0404e jdk8u75-b02
@@ -552,6 +562,14 @@
 22ba4f1ad75c80bf78539f4c80b9867d227184d3 jdk8u75-b09
 9da1d3f8905be682e33579857dd7b176f847e938 jdk8u75-b10
 d8708cd521ff11851b259cd1171e8f18b90564a1 jdk8u75-b12
+417ff12d11d60c7f2235b498fdea9ef85514fc75 jdk8u77-b00
+6683e1d7422d0b6fc6566a1454604ca1ba7e86d9 jdk8u77-b01
+7dd1be8bd46cd4c80526671607e8035c3c671c14 jdk8u77-b02
+3fbef9f4cddf934f9cc0e06f61e641b5b845b901 jdk8u77-b03
+08dc508915433fdf3d970ea4d2fd33b4dffd67ca jdk8u77-b31
+4c41657db1862352b0e107b910be32c86eb5b1ff jdk8u91-b00
+0c798868f18548af144de0f0ab69f09a4c968cd2 jdk8u91-b13
+5744173381186940733aecf7904053ba6e83180e jdk8u91-b14
 e8bed1496ff254d91d52c8da7c6d8d361862d773 jdk8u76-b00
 832508a6165c877aa1de03ca9b6520c7bfe5a28e jdk8u76-b01
 0861105394355ad24c07cb2ff58a731ef91502a8 jdk8u76-b02
@@ -564,3 +582,7 @@
 b5e3d2c78818af23d855cb10bac51fab5b7b2884 jdk8u76-b09
 2377ea341a26d0a6875f148dc555811bdf2e9533 jdk8u76-b10
 94746373e4d5590536bacb0df4a19188e4d1bdd8 jdk8u76-b11
+9f2404d26c945178219c4f826fee5a084896ba55 jdk8u76-b12
+118aba9e37f0264a7cadb20ac0438eaea4180998 jdk8u92-b00
+94158f2e5cbdff8956b8e643e0305ca178d856e3 jdk8u92-b13
+51f64c980bcdef152a6eb043aaa5d04cc08c6624 jdk8u92-b14
diff --git a/corba/.hgtags b/corba/.hgtags
index 1bc8128..3b64265 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -542,6 +542,19 @@
 0ce690c17329bde61998e5cd30b1beec9872262f jdk8u74-b01
 5eb60567655e15d7ba4c349658d707f5bde0c2b8 jdk8u74-b02
 d82cbb7a4bfe21b146f7b91ce833ac5a579c94eb jdk8u72-b31
+e3b496b6ae52f2c018e9c628c31be984bb4907e7 jdk8u73-b00
+5e484ab4b05f1398e924ab90874f7fe2ddf20731 jdk8u73-b01
+0cfcffb354bb4c76cac46f52b16a50e3b57794b9 jdk8u73-b02
+9e88cf03fe09fbf33045f43489be6f9c00e80c35 jdk8u74-b00
+0ce690c17329bde61998e5cd30b1beec9872262f jdk8u74-b01
+5eb60567655e15d7ba4c349658d707f5bde0c2b8 jdk8u74-b02
+3d00f5689b6c6e71fb1a230b7a746b61569b90ec jdk8u74-b31
+0cec2665affa36496b906c566e22ba7048ae6087 jdk8u74-b32
+7b719c1dec62535c34030cf3457abe6f478f13a0 jdk8u77-b00
+cafc1648f432eff2c392040af2db4505c3d290b6 jdk8u77-b01
+0f0077ee5e53365562ff77a01aa97d0c7374f447 jdk8u77-b02
+e8dc6eb11c761f20b44d8c4b8acb0846268872f1 jdk8u77-b03
+af6ddd4cd94c9353cc053b888de6d42d4d0faf47 jdk8u77-b31
 073b951904b3ee7c54fb79a169478fa66d925320 jdk8u75-b00
 5b48f7defe40eab668fe554df0afd87d84d60722 jdk8u75-b01
 0015f4a7f0d02a9bb79b7a0c737590f01feaabd4 jdk8u75-b02
@@ -554,6 +567,13 @@
 1030aea873cdecfb6f55ab652abc67c901f61f60 jdk8u75-b09
 964fe4bba121592325cb346e3a4fa677b277d0ec jdk8u75-b10
 f7cfd44464c3c3efd6d6f29921fad4ed0de75d83 jdk8u75-b12
+7b719c1dec62535c34030cf3457abe6f478f13a0 jdk8u77-b00
+cafc1648f432eff2c392040af2db4505c3d290b6 jdk8u77-b01
+0f0077ee5e53365562ff77a01aa97d0c7374f447 jdk8u77-b02
+e8dc6eb11c761f20b44d8c4b8acb0846268872f1 jdk8u77-b03
+cd7cec8fd295c0462a813b5f54dc5457c2bade2d jdk8u91-b00
+4ea02753e66e348ee4639e157061bcbdef1d7ff3 jdk8u91-b13
+f8d0cfaa9900ebda679fa9df8319fb753858f283 jdk8u91-b14
 7deeb4f70404e4f52306f9d0bcfc482fc5f16fb3 jdk8u76-b00
 5786892e7c7d512ef9104a469ff7eafeaac12c38 jdk8u76-b01
 239155e48af89968b62e695a3233d42bed1a3282 jdk8u76-b02
@@ -566,3 +586,7 @@
 afb55372bcc787b75e24afd28b00cfaaa45bb77d jdk8u76-b09
 d2f26e6433db89354b028fb75abcc6ca266d035f jdk8u76-b10
 df2dcefb08f9e3c65a4cbea75e54600649d063d0 jdk8u76-b11
+94c775e05eb053b8440d82298927a144ed73f340 jdk8u76-b12
+e0fbd6a51e061025f2d6ad0311a587f7ce3c2b43 jdk8u92-b00
+8f0466c0dce60b1df3bc01785b01a7f09fa7b564 jdk8u92-b13
+5617f9bec354fb2c60bbb816d175f4cee7d2c56e jdk8u92-b14
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 091c179..6165d68 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -801,12 +801,20 @@
 a8e4754b89aecc388623394a20f6d43d4c58f083 jdk8u72-b13
 dc2fdd4e0b8105268b8231040f761f27ab4523f2 jdk8u72-b14
 d6670c5d49ba381405ec9f69a78ccc5b8b0c8473 jdk8u72-b15
+da43260704c28b9f19cb652090ae65c258220fd6 jdk8u72-b31
 26b99cd20661a1fa05939d1856a9389311e01c4f jdk8u73-b00
 931c31db01ae873525a1b2c306b01129eb431960 jdk8u73-b01
 67566d815a66d958c1f817d65f1621ba1d2e5f33 jdk8u73-b02
 451dda77f6c29bd3260e87f847a9eadae122a759 jdk8u74-b00
 c1031a924f2c910fad078838b88a2f0146f2de98 jdk8u74-b01
 ca9cae9aa9e989bbe6713c91d55c913edeaecce4 jdk8u74-b02
+a5b78b56841e97ce00463874f1b7f63c54d84934 jdk8u74-b31
+94ec11846b18111e73929b6caa9fbe7262e142c1 jdk8u74-b32
+1b6d4fd2730e58f17820930f797938dc182117c4 jdk8u77-b00
+ddd297e340b1170d3cec011ee64e729f8b493c86 jdk8u77-b01
+1b4072e4bb3ad54c4e894998486a8b33f0689160 jdk8u77-b02
+223b64a19e94222dd97b92bb40abcfbc0bf6ef1f jdk8u77-b03
+dd8507f51d786572dae18af8ffdc5a1ea34c755e jdk8u77-b31
 da43260704c28b9f19cb652090ae65c258220fd6 jdk8u72-b31
 c0242ea4bde19d72be5149feda112a39e8c89b0a jdk8u75-b00
 ca3b8c8e390ab0540b0cc2e5def869b38e460d86 jdk8u75-b01
@@ -820,6 +828,13 @@
 e97c45c377eb8d022cfe24b73737fa312107e0a5 jdk8u75-b09
 d44c7e324682a30e064503ef9582d83a41f4173e jdk8u75-b10
 cc78c97abff85062d6844fa253081e26a0a60150 jdk8u75-b12
+1b6d4fd2730e58f17820930f797938dc182117c4 jdk8u77-b00
+ddd297e340b1170d3cec011ee64e729f8b493c86 jdk8u77-b01
+1b4072e4bb3ad54c4e894998486a8b33f0689160 jdk8u77-b02
+223b64a19e94222dd97b92bb40abcfbc0bf6ef1f jdk8u77-b03
+bbbb05e91c629f8d9eef2ba43933767f68a898b0 jdk8u91-b00
+e36b6ade0499eadfd8673fe62ef0a613af2e6d67 jdk8u91-b13
+fa8991ccf6e5b74890a0b5672440b3c09d8d8732 jdk8u91-b14
 d7b01fb81aa8a5437cb03bc36afe15cf0e55fb89 jdk8u76-b00
 c1679cc87ba045219169cabb6b9b378c2b5cc578 jdk8u76-b01
 218483967e52b419d885d34af4488a81c5133804 jdk8u76-b02
@@ -832,3 +847,7 @@
 3bf0f5b8a892defd0bf9731b4e15926881fcda74 jdk8u76-b09
 a2b0ee820059a44be558a2d435b7d85ed5a8b63a jdk8u76-b10
 16aa1f621ec67db1a55ebf6527750164ab63088d jdk8u76-b11
+9a87701e22b3cae79fdfd8cdb732051e02a710fa jdk8u76-b12
+481dcde745b6aec035781ed9f6797cfc93719f71 jdk8u92-b00
+f3e1e734e2d29101a9537ddeb71ecad413fcd352 jdk8u92-b13
+24a09407d71bb2cc4848bfa21660c890b4d722b1 jdk8u92-b14
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
index 8098e88..7cbc47d 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
@@ -2318,6 +2318,13 @@
   emit_arith(0x0B, 0xC0, dst, src);
 }
 
+void Assembler::orl(Address dst, Register src) {
+  InstructionMark im(this);
+  prefix(dst, src);
+  emit_int8(0x09);
+  emit_operand(src, dst);
+}
+
 void Assembler::packuswb(XMMRegister dst, Address src) {
   NOT_LP64(assert(VM_Version::supports_sse2(), ""));
   assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
@@ -5613,6 +5620,19 @@
   }
 }
 
+void Assembler::rcrq(Register dst, int imm8) {
+  assert(isShiftCount(imm8 >> 1), "illegal shift count");
+  int encode = prefixq_and_encode(dst->encoding());
+  if (imm8 == 1) {
+    emit_int8((unsigned char)0xD1);
+    emit_int8((unsigned char)(0xD8 | encode));
+  } else {
+    emit_int8((unsigned char)0xC1);
+    emit_int8((unsigned char)(0xD8 | encode));
+    emit_int8(imm8);
+  }
+}
+
 void Assembler::rorq(Register dst, int imm8) {
   assert(isShiftCount(imm8 >> 1), "illegal shift count");
   int encode = prefixq_and_encode(dst->encoding());
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
index fc270db..341d9e3 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
@@ -1455,6 +1455,7 @@
   void orl(Register dst, int32_t imm32);
   void orl(Register dst, Address src);
   void orl(Register dst, Register src);
+  void orl(Address dst, Register src);
 
   void orq(Address dst, int32_t imm32);
   void orq(Register dst, int32_t imm32);
@@ -1555,6 +1556,8 @@
 
   void rclq(Register dst, int imm8);
 
+  void rcrq(Register dst, int imm8);
+
   void rdtsc();
 
   void ret(int imm16);
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
index b3a72ab..e2ea04b 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -7769,6 +7769,503 @@
   pop(tmp2);
   pop(tmp1);
 }
+
+//Helper functions for square_to_len()
+
+/**
+ * Store the squares of x[], right shifted one bit (divided by 2) into z[]
+ * Preserves x and z and modifies rest of the registers.
+ */
+
+void MacroAssembler::square_rshift(Register x, Register xlen, Register z, Register tmp1, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg) {
+  // Perform square and right shift by 1
+  // Handle odd xlen case first, then for even xlen do the following
+  // jlong carry = 0;
+  // for (int j=0, i=0; j < xlen; j+=2, i+=4) {
+  //     huge_128 product = x[j:j+1] * x[j:j+1];
+  //     z[i:i+1] = (carry << 63) | (jlong)(product >>> 65);
+  //     z[i+2:i+3] = (jlong)(product >>> 1);
+  //     carry = (jlong)product;
+  // }
+
+  xorq(tmp5, tmp5);     // carry
+  xorq(rdxReg, rdxReg);
+  xorl(tmp1, tmp1);     // index for x
+  xorl(tmp4, tmp4);     // index for z
+
+  Label L_first_loop, L_first_loop_exit;
+
+  testl(xlen, 1);
+  jccb(Assembler::zero, L_first_loop); //jump if xlen is even
+
+  // Square and right shift by 1 the odd element using 32 bit multiply
+  movl(raxReg, Address(x, tmp1, Address::times_4, 0));
+  imulq(raxReg, raxReg);
+  shrq(raxReg, 1);
+  adcq(tmp5, 0);
+  movq(Address(z, tmp4, Address::times_4, 0), raxReg);
+  incrementl(tmp1);
+  addl(tmp4, 2);
+
+  // Square and  right shift by 1 the rest using 64 bit multiply
+  bind(L_first_loop);
+  cmpptr(tmp1, xlen);
+  jccb(Assembler::equal, L_first_loop_exit);
+
+  // Square
+  movq(raxReg, Address(x, tmp1, Address::times_4,  0));
+  rorq(raxReg, 32);    // convert big-endian to little-endian
+  mulq(raxReg);        // 64-bit multiply rax * rax -> rdx:rax
+
+  // Right shift by 1 and save carry
+  shrq(tmp5, 1);       // rdx:rax:tmp5 = (tmp5:rdx:rax) >>> 1
+  rcrq(rdxReg, 1);
+  rcrq(raxReg, 1);
+  adcq(tmp5, 0);
+
+  // Store result in z
+  movq(Address(z, tmp4, Address::times_4, 0), rdxReg);
+  movq(Address(z, tmp4, Address::times_4, 8), raxReg);
+
+  // Update indices for x and z
+  addl(tmp1, 2);
+  addl(tmp4, 4);
+  jmp(L_first_loop);
+
+  bind(L_first_loop_exit);
+}
+
+
+/**
+ * Perform the following multiply add operation using BMI2 instructions
+ * carry:sum = sum + op1*op2 + carry
+ * op2 should be in rdx
+ * op2 is preserved, all other registers are modified
+ */
+void MacroAssembler::multiply_add_64_bmi2(Register sum, Register op1, Register op2, Register carry, Register tmp2) {
+  // assert op2 is rdx
+  mulxq(tmp2, op1, op1);  //  op1 * op2 -> tmp2:op1
+  addq(sum, carry);
+  adcq(tmp2, 0);
+  addq(sum, op1);
+  adcq(tmp2, 0);
+  movq(carry, tmp2);
+}
+
+/**
+ * Perform the following multiply add operation:
+ * carry:sum = sum + op1*op2 + carry
+ * Preserves op1, op2 and modifies rest of registers
+ */
+void MacroAssembler::multiply_add_64(Register sum, Register op1, Register op2, Register carry, Register rdxReg, Register raxReg) {
+  // rdx:rax = op1 * op2
+  movq(raxReg, op2);
+  mulq(op1);
+
+  //  rdx:rax = sum + carry + rdx:rax
+  addq(sum, carry);
+  adcq(rdxReg, 0);
+  addq(sum, raxReg);
+  adcq(rdxReg, 0);
+
+  // carry:sum = rdx:sum
+  movq(carry, rdxReg);
+}
+
+/**
+ * Add 64 bit long carry into z[] with carry propogation.
+ * Preserves z and carry register values and modifies rest of registers.
+ *
+ */
+void MacroAssembler::add_one_64(Register z, Register zlen, Register carry, Register tmp1) {
+  Label L_fourth_loop, L_fourth_loop_exit;
+
+  movl(tmp1, 1);
+  subl(zlen, 2);
+  addq(Address(z, zlen, Address::times_4, 0), carry);
+
+  bind(L_fourth_loop);
+  jccb(Assembler::carryClear, L_fourth_loop_exit);
+  subl(zlen, 2);
+  jccb(Assembler::negative, L_fourth_loop_exit);
+  addq(Address(z, zlen, Address::times_4, 0), tmp1);
+  jmp(L_fourth_loop);
+  bind(L_fourth_loop_exit);
+}
+
+/**
+ * Shift z[] left by 1 bit.
+ * Preserves x, len, z and zlen registers and modifies rest of the registers.
+ *
+ */
+void MacroAssembler::lshift_by_1(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4) {
+
+  Label L_fifth_loop, L_fifth_loop_exit;
+
+  // Fifth loop
+  // Perform primitiveLeftShift(z, zlen, 1)
+
+  const Register prev_carry = tmp1;
+  const Register new_carry = tmp4;
+  const Register value = tmp2;
+  const Register zidx = tmp3;
+
+  // int zidx, carry;
+  // long value;
+  // carry = 0;
+  // for (zidx = zlen-2; zidx >=0; zidx -= 2) {
+  //    (carry:value)  = (z[i] << 1) | carry ;
+  //    z[i] = value;
+  // }
+
+  movl(zidx, zlen);
+  xorl(prev_carry, prev_carry); // clear carry flag and prev_carry register
+
+  bind(L_fifth_loop);
+  decl(zidx);  // Use decl to preserve carry flag
+  decl(zidx);
+  jccb(Assembler::negative, L_fifth_loop_exit);
+
+  if (UseBMI2Instructions) {
+     movq(value, Address(z, zidx, Address::times_4, 0));
+     rclq(value, 1);
+     rorxq(value, value, 32);
+     movq(Address(z, zidx, Address::times_4,  0), value);  // Store back in big endian form
+  }
+  else {
+    // clear new_carry
+    xorl(new_carry, new_carry);
+
+    // Shift z[i] by 1, or in previous carry and save new carry
+    movq(value, Address(z, zidx, Address::times_4, 0));
+    shlq(value, 1);
+    adcl(new_carry, 0);
+
+    orq(value, prev_carry);
+    rorq(value, 0x20);
+    movq(Address(z, zidx, Address::times_4,  0), value);  // Store back in big endian form
+
+    // Set previous carry = new carry
+    movl(prev_carry, new_carry);
+  }
+  jmp(L_fifth_loop);
+
+  bind(L_fifth_loop_exit);
+}
+
+
+/**
+ * Code for BigInteger::squareToLen() intrinsic
+ *
+ * rdi: x
+ * rsi: len
+ * r8:  z
+ * rcx: zlen
+ * r12: tmp1
+ * r13: tmp2
+ * r14: tmp3
+ * r15: tmp4
+ * rbx: tmp5
+ *
+ */
+void MacroAssembler::square_to_len(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg) {
+
+  Label L_second_loop, L_second_loop_exit, L_third_loop, L_third_loop_exit, fifth_loop, fifth_loop_exit, L_last_x, L_multiply;
+  push(tmp1);
+  push(tmp2);
+  push(tmp3);
+  push(tmp4);
+  push(tmp5);
+
+  // First loop
+  // Store the squares, right shifted one bit (i.e., divided by 2).
+  square_rshift(x, len, z, tmp1, tmp3, tmp4, tmp5, rdxReg, raxReg);
+
+  // Add in off-diagonal sums.
+  //
+  // Second, third (nested) and fourth loops.
+  // zlen +=2;
+  // for (int xidx=len-2,zidx=zlen-4; xidx > 0; xidx-=2,zidx-=4) {
+  //    carry = 0;
+  //    long op2 = x[xidx:xidx+1];
+  //    for (int j=xidx-2,k=zidx; j >= 0; j-=2) {
+  //       k -= 2;
+  //       long op1 = x[j:j+1];
+  //       long sum = z[k:k+1];
+  //       carry:sum = multiply_add_64(sum, op1, op2, carry, tmp_regs);
+  //       z[k:k+1] = sum;
+  //    }
+  //    add_one_64(z, k, carry, tmp_regs);
+  // }
+
+  const Register carry = tmp5;
+  const Register sum = tmp3;
+  const Register op1 = tmp4;
+  Register op2 = tmp2;
+
+  push(zlen);
+  push(len);
+  addl(zlen,2);
+  bind(L_second_loop);
+  xorq(carry, carry);
+  subl(zlen, 4);
+  subl(len, 2);
+  push(zlen);
+  push(len);
+  cmpl(len, 0);
+  jccb(Assembler::lessEqual, L_second_loop_exit);
+
+  // Multiply an array by one 64 bit long.
+  if (UseBMI2Instructions) {
+    op2 = rdxReg;
+    movq(op2, Address(x, len, Address::times_4,  0));
+    rorxq(op2, op2, 32);
+  }
+  else {
+    movq(op2, Address(x, len, Address::times_4,  0));
+    rorq(op2, 32);
+  }
+
+  bind(L_third_loop);
+  decrementl(len);
+  jccb(Assembler::negative, L_third_loop_exit);
+  decrementl(len);
+  jccb(Assembler::negative, L_last_x);
+
+  movq(op1, Address(x, len, Address::times_4,  0));
+  rorq(op1, 32);
+
+  bind(L_multiply);
+  subl(zlen, 2);
+  movq(sum, Address(z, zlen, Address::times_4,  0));
+
+  // Multiply 64 bit by 64 bit and add 64 bits lower half and upper 64 bits as carry.
+  if (UseBMI2Instructions) {
+    multiply_add_64_bmi2(sum, op1, op2, carry, tmp2);
+  }
+  else {
+    multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg);
+  }
+
+  movq(Address(z, zlen, Address::times_4, 0), sum);
+
+  jmp(L_third_loop);
+  bind(L_third_loop_exit);
+
+  // Fourth loop
+  // Add 64 bit long carry into z with carry propogation.
+  // Uses offsetted zlen.
+  add_one_64(z, zlen, carry, tmp1);
+
+  pop(len);
+  pop(zlen);
+  jmp(L_second_loop);
+
+  // Next infrequent code is moved outside loops.
+  bind(L_last_x);
+  movl(op1, Address(x, 0));
+  jmp(L_multiply);
+
+  bind(L_second_loop_exit);
+  pop(len);
+  pop(zlen);
+  pop(len);
+  pop(zlen);
+
+  // Fifth loop
+  // Shift z left 1 bit.
+  lshift_by_1(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4);
+
+  // z[zlen-1] |= x[len-1] & 1;
+  movl(tmp3, Address(x, len, Address::times_4, -4));
+  andl(tmp3, 1);
+  orl(Address(z, zlen, Address::times_4,  -4), tmp3);
+
+  pop(tmp5);
+  pop(tmp4);
+  pop(tmp3);
+  pop(tmp2);
+  pop(tmp1);
+}
+
+/**
+ * Helper function for mul_add()
+ * Multiply the in[] by int k and add to out[] starting at offset offs using
+ * 128 bit by 32 bit multiply and return the carry in tmp5.
+ * Only quad int aligned length of in[] is operated on in this function.
+ * k is in rdxReg for BMI2Instructions, for others it is in tmp2.
+ * This function preserves out, in and k registers.
+ * len and offset point to the appropriate index in "in" & "out" correspondingly
+ * tmp5 has the carry.
+ * other registers are temporary and are modified.
+ *
+ */
+void MacroAssembler::mul_add_128_x_32_loop(Register out, Register in,
+  Register offset, Register len, Register tmp1, Register tmp2, Register tmp3,
+  Register tmp4, Register tmp5, Register rdxReg, Register raxReg) {
+
+  Label L_first_loop, L_first_loop_exit;
+
+  movl(tmp1, len);
+  shrl(tmp1, 2);
+
+  bind(L_first_loop);
+  subl(tmp1, 1);
+  jccb(Assembler::negative, L_first_loop_exit);
+
+  subl(len, 4);
+  subl(offset, 4);
+
+  Register op2 = tmp2;
+  const Register sum = tmp3;
+  const Register op1 = tmp4;
+  const Register carry = tmp5;
+
+  if (UseBMI2Instructions) {
+    op2 = rdxReg;
+  }
+
+  movq(op1, Address(in, len, Address::times_4,  8));
+  rorq(op1, 32);
+  movq(sum, Address(out, offset, Address::times_4,  8));
+  rorq(sum, 32);
+  if (UseBMI2Instructions) {
+    multiply_add_64_bmi2(sum, op1, op2, carry, raxReg);
+  }
+  else {
+    multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg);
+  }
+  // Store back in big endian from little endian
+  rorq(sum, 0x20);
+  movq(Address(out, offset, Address::times_4,  8), sum);
+
+  movq(op1, Address(in, len, Address::times_4,  0));
+  rorq(op1, 32);
+  movq(sum, Address(out, offset, Address::times_4,  0));
+  rorq(sum, 32);
+  if (UseBMI2Instructions) {
+    multiply_add_64_bmi2(sum, op1, op2, carry, raxReg);
+  }
+  else {
+    multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg);
+  }
+  // Store back in big endian from little endian
+  rorq(sum, 0x20);
+  movq(Address(out, offset, Address::times_4,  0), sum);
+
+  jmp(L_first_loop);
+  bind(L_first_loop_exit);
+}
+
+/**
+ * Code for BigInteger::mulAdd() intrinsic
+ *
+ * rdi: out
+ * rsi: in
+ * r11: offs (out.length - offset)
+ * rcx: len
+ * r8:  k
+ * r12: tmp1
+ * r13: tmp2
+ * r14: tmp3
+ * r15: tmp4
+ * rbx: tmp5
+ * Multiply the in[] by word k and add to out[], return the carry in rax
+ */
+void MacroAssembler::mul_add(Register out, Register in, Register offs,
+   Register len, Register k, Register tmp1, Register tmp2, Register tmp3,
+   Register tmp4, Register tmp5, Register rdxReg, Register raxReg) {
+
+  Label L_carry, L_last_in, L_done;
+
+// carry = 0;
+// for (int j=len-1; j >= 0; j--) {
+//    long product = (in[j] & LONG_MASK) * kLong +
+//                   (out[offs] & LONG_MASK) + carry;
+//    out[offs--] = (int)product;
+//    carry = product >>> 32;
+// }
+//
+  push(tmp1);
+  push(tmp2);
+  push(tmp3);
+  push(tmp4);
+  push(tmp5);
+
+  Register op2 = tmp2;
+  const Register sum = tmp3;
+  const Register op1 = tmp4;
+  const Register carry =  tmp5;
+
+  if (UseBMI2Instructions) {
+    op2 = rdxReg;
+    movl(op2, k);
+  }
+  else {
+    movl(op2, k);
+  }
+
+  xorq(carry, carry);
+
+  //First loop
+
+  //Multiply in[] by k in a 4 way unrolled loop using 128 bit by 32 bit multiply
+  //The carry is in tmp5
+  mul_add_128_x_32_loop(out, in, offs, len, tmp1, tmp2, tmp3, tmp4, tmp5, rdxReg, raxReg);
+
+  //Multiply the trailing in[] entry using 64 bit by 32 bit, if any
+  decrementl(len);
+  jccb(Assembler::negative, L_carry);
+  decrementl(len);
+  jccb(Assembler::negative, L_last_in);
+
+  movq(op1, Address(in, len, Address::times_4,  0));
+  rorq(op1, 32);
+
+  subl(offs, 2);
+  movq(sum, Address(out, offs, Address::times_4,  0));
+  rorq(sum, 32);
+
+  if (UseBMI2Instructions) {
+    multiply_add_64_bmi2(sum, op1, op2, carry, raxReg);
+  }
+  else {
+    multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg);
+  }
+
+  // Store back in big endian from little endian
+  rorq(sum, 0x20);
+  movq(Address(out, offs, Address::times_4,  0), sum);
+
+  testl(len, len);
+  jccb(Assembler::zero, L_carry);
+
+  //Multiply the last in[] entry, if any
+  bind(L_last_in);
+  movl(op1, Address(in, 0));
+  movl(sum, Address(out, offs, Address::times_4,  -4));
+
+  movl(raxReg, k);
+  mull(op1); //tmp4 * eax -> edx:eax
+  addl(sum, carry);
+  adcl(rdxReg, 0);
+  addl(sum, raxReg);
+  adcl(rdxReg, 0);
+  movl(carry, rdxReg);
+
+  movl(Address(out, offs, Address::times_4,  -4), sum);
+
+  bind(L_carry);
+  //return tmp5/carry as carry in rax
+  movl(rax, carry);
+
+  bind(L_done);
+  pop(tmp5);
+  pop(tmp4);
+  pop(tmp3);
+  pop(tmp2);
+  pop(tmp1);
+}
 #endif
 
 /**
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
index 69c9e8a..cc5e585 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -1241,6 +1241,25 @@
                                Register carry2);
   void multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z, Register zlen,
                        Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5);
+
+  void square_rshift(Register x, Register len, Register z, Register tmp1, Register tmp3,
+                     Register tmp4, Register tmp5, Register rdxReg, Register raxReg);
+  void multiply_add_64_bmi2(Register sum, Register op1, Register op2, Register carry,
+                            Register tmp2);
+  void multiply_add_64(Register sum, Register op1, Register op2, Register carry,
+                       Register rdxReg, Register raxReg);
+  void add_one_64(Register z, Register zlen, Register carry, Register tmp1);
+  void lshift_by_1(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2,
+                       Register tmp3, Register tmp4);
+  void square_to_len(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2,
+                     Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg);
+
+  void mul_add_128_x_32_loop(Register out, Register in, Register offset, Register len, Register tmp1,
+               Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg,
+               Register raxReg);
+  void mul_add(Register out, Register in, Register offset, Register len, Register k, Register tmp1,
+               Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg,
+               Register raxReg);
 #endif
 
   // CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic.
diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
index 86ce38d..a3eb504 100644
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
@@ -23,6 +23,9 @@
  */
 
 #include "precompiled.hpp"
+#ifndef _WINDOWS
+#include "alloca.h"
+#endif
 #include "asm/macroAssembler.hpp"
 #include "asm/macroAssembler.inline.hpp"
 #include "code/debugInfoRec.hpp"
@@ -3966,6 +3969,256 @@
 }
 
 
+//------------------------------Montgomery multiplication------------------------
+//
+
+#ifndef _WINDOWS
+
+#define ASM_SUBTRACT
+
+#ifdef ASM_SUBTRACT
+// Subtract 0:b from carry:a.  Return carry.
+static unsigned long
+sub(unsigned long a[], unsigned long b[], unsigned long carry, long len) {
+  long i = 0, cnt = len;
+  unsigned long tmp;
+  asm volatile("clc; "
+               "0: ; "
+               "mov (%[b], %[i], 8), %[tmp]; "
+               "sbb %[tmp], (%[a], %[i], 8); "
+               "inc %[i]; dec %[cnt]; "
+               "jne 0b; "
+               "mov %[carry], %[tmp]; sbb $0, %[tmp]; "
+               : [i]"+r"(i), [cnt]"+r"(cnt), [tmp]"=&r"(tmp)
+               : [a]"r"(a), [b]"r"(b), [carry]"r"(carry)
+               : "memory");
+  return tmp;
+}
+#else // ASM_SUBTRACT
+typedef int __attribute__((mode(TI))) int128;
+
+// Subtract 0:b from carry:a.  Return carry.
+static unsigned long
+sub(unsigned long a[], unsigned long b[], unsigned long carry, int len) {
+  int128 tmp = 0;
+  int i;
+  for (i = 0; i < len; i++) {
+    tmp += a[i];
+    tmp -= b[i];
+    a[i] = tmp;
+    tmp >>= 64;
+    assert(-1 <= tmp && tmp <= 0, "invariant");
+  }
+  return tmp + carry;
+}
+#endif // ! ASM_SUBTRACT
+
+// Multiply (unsigned) Long A by Long B, accumulating the double-
+// length result into the accumulator formed of T0, T1, and T2.
+#define MACC(A, B, T0, T1, T2)                                      \
+do {                                                                \
+  unsigned long hi, lo;                                             \
+  asm volatile("mul %5; add %%rax, %2; adc %%rdx, %3; adc $0, %4"   \
+           : "=&d"(hi), "=a"(lo), "+r"(T0), "+r"(T1), "+g"(T2)      \
+           : "r"(A), "a"(B) : "cc");                                \
+ } while(0)
+
+// As above, but add twice the double-length result into the
+// accumulator.
+#define MACC2(A, B, T0, T1, T2)                                     \
+do {                                                                \
+  unsigned long hi, lo;                                             \
+  asm volatile("mul %5; add %%rax, %2; adc %%rdx, %3; adc $0, %4;"  \
+           "add %%rax, %2; adc %%rdx, %3; adc $0, %4"               \
+           : "=&d"(hi), "=a"(lo), "+r"(T0), "+r"(T1), "+g"(T2)      \
+           : "r"(A), "a"(B) : "cc");                                \
+ } while(0)
+
+// Fast Montgomery multiplication.  The derivation of the algorithm is
+// in  A Cryptographic Library for the Motorola DSP56000,
+// Dusse and Kaliski, Proc. EUROCRYPT 90, pp. 230-237.
+
+static void __attribute__((noinline))
+montgomery_multiply(unsigned long a[], unsigned long b[], unsigned long n[],
+                    unsigned long m[], unsigned long inv, int len) {
+  unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator
+  int i;
+
+  assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply");
+
+  for (i = 0; i < len; i++) {
+    int j;
+    for (j = 0; j < i; j++) {
+      MACC(a[j], b[i-j], t0, t1, t2);
+      MACC(m[j], n[i-j], t0, t1, t2);
+    }
+    MACC(a[i], b[0], t0, t1, t2);
+    m[i] = t0 * inv;
+    MACC(m[i], n[0], t0, t1, t2);
+
+    assert(t0 == 0, "broken Montgomery multiply");
+
+    t0 = t1; t1 = t2; t2 = 0;
+  }
+
+  for (i = len; i < 2*len; i++) {
+    int j;
+    for (j = i-len+1; j < len; j++) {
+      MACC(a[j], b[i-j], t0, t1, t2);
+      MACC(m[j], n[i-j], t0, t1, t2);
+    }
+    m[i-len] = t0;
+    t0 = t1; t1 = t2; t2 = 0;
+  }
+
+  while (t0)
+    t0 = sub(m, n, t0, len);
+}
+
+// Fast Montgomery squaring.  This uses asymptotically 25% fewer
+// multiplies so it should be up to 25% faster than Montgomery
+// multiplication.  However, its loop control is more complex and it
+// may actually run slower on some machines.
+
+static void __attribute__((noinline))
+montgomery_square(unsigned long a[], unsigned long n[],
+                  unsigned long m[], unsigned long inv, int len) {
+  unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator
+  int i;
+
+  assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply");
+
+  for (i = 0; i < len; i++) {
+    int j;
+    int end = (i+1)/2;
+    for (j = 0; j < end; j++) {
+      MACC2(a[j], a[i-j], t0, t1, t2);
+      MACC(m[j], n[i-j], t0, t1, t2);
+    }
+    if ((i & 1) == 0) {
+      MACC(a[j], a[j], t0, t1, t2);
+    }
+    for (; j < i; j++) {
+      MACC(m[j], n[i-j], t0, t1, t2);
+    }
+    m[i] = t0 * inv;
+    MACC(m[i], n[0], t0, t1, t2);
+
+    assert(t0 == 0, "broken Montgomery square");
+
+    t0 = t1; t1 = t2; t2 = 0;
+  }
+
+  for (i = len; i < 2*len; i++) {
+    int start = i-len+1;
+    int end = start + (len - start)/2;
+    int j;
+    for (j = start; j < end; j++) {
+      MACC2(a[j], a[i-j], t0, t1, t2);
+      MACC(m[j], n[i-j], t0, t1, t2);
+    }
+    if ((i & 1) == 0) {
+      MACC(a[j], a[j], t0, t1, t2);
+    }
+    for (; j < len; j++) {
+      MACC(m[j], n[i-j], t0, t1, t2);
+    }
+    m[i-len] = t0;
+    t0 = t1; t1 = t2; t2 = 0;
+  }
+
+  while (t0)
+    t0 = sub(m, n, t0, len);
+}
+
+// Swap words in a longword.
+static unsigned long swap(unsigned long x) {
+  return (x << 32) | (x >> 32);
+}
+
+// Copy len longwords from s to d, word-swapping as we go.  The
+// destination array is reversed.
+static void reverse_words(unsigned long *s, unsigned long *d, int len) {
+  d += len;
+  while(len-- > 0) {
+    d--;
+    *d = swap(*s);
+    s++;
+  }
+}
+
+// The threshold at which squaring is advantageous was determined
+// experimentally on an i7-3930K (Ivy Bridge) CPU @ 3.5GHz.
+#define MONTGOMERY_SQUARING_THRESHOLD 64
+
+void SharedRuntime::montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints,
+                                        jint len, jlong inv,
+                                        jint *m_ints) {
+  assert(len % 2 == 0, "array length in montgomery_multiply must be even");
+  int longwords = len/2;
+
+  // Make very sure we don't use so much space that the stack might
+  // overflow.  512 jints corresponds to an 16384-bit integer and
+  // will use here a total of 8k bytes of stack space.
+  int total_allocation = longwords * sizeof (unsigned long) * 4;
+  guarantee(total_allocation <= 8192, "must be");
+  unsigned long *scratch = (unsigned long *)alloca(total_allocation);
+
+  // Local scratch arrays
+  unsigned long
+    *a = scratch + 0 * longwords,
+    *b = scratch + 1 * longwords,
+    *n = scratch + 2 * longwords,
+    *m = scratch + 3 * longwords;
+
+  reverse_words((unsigned long *)a_ints, a, longwords);
+  reverse_words((unsigned long *)b_ints, b, longwords);
+  reverse_words((unsigned long *)n_ints, n, longwords);
+
+  ::montgomery_multiply(a, b, n, m, (unsigned long)inv, longwords);
+
+  reverse_words(m, (unsigned long *)m_ints, longwords);
+}
+
+void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints,
+                                      jint len, jlong inv,
+                                      jint *m_ints) {
+  assert(len % 2 == 0, "array length in montgomery_square must be even");
+  int longwords = len/2;
+
+  // Make very sure we don't use so much space that the stack might
+  // overflow.  512 jints corresponds to an 16384-bit integer and
+  // will use here a total of 6k bytes of stack space.
+  int total_allocation = longwords * sizeof (unsigned long) * 3;
+  guarantee(total_allocation <= 8192, "must be");
+  unsigned long *scratch = (unsigned long *)alloca(total_allocation);
+
+  // Local scratch arrays
+  unsigned long
+    *a = scratch + 0 * longwords,
+    *n = scratch + 1 * longwords,
+    *m = scratch + 2 * longwords;
+
+  reverse_words((unsigned long *)a_ints, a, longwords);
+  reverse_words((unsigned long *)n_ints, n, longwords);
+
+  //montgomery_square fails to pass BigIntegerTest on solaris amd64
+  //on jdk7 and jdk8.
+#ifndef SOLARIS
+  if (len >= MONTGOMERY_SQUARING_THRESHOLD) {
+#else
+  if (0) {
+#endif
+    ::montgomery_square(a, n, m, (unsigned long)inv, longwords);
+  } else {
+    ::montgomery_multiply(a, a, n, m, (unsigned long)inv, longwords);
+  }
+
+  reverse_words(m, (unsigned long *)m_ints, longwords);
+}
+
+#endif // WINDOWS
+
 #ifdef COMPILER2
 // This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame
 //
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index 0bb6118..01fe4b8 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -3743,6 +3743,107 @@
     return start;
   }
 
+/**
+   *  Arguments:
+   *
+  //  Input:
+  //    c_rarg0   - x address
+  //    c_rarg1   - x length
+  //    c_rarg2   - z address
+  //    c_rarg3   - z lenth
+   *
+   */
+  address generate_squareToLen() {
+
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", "squareToLen");
+
+    address start = __ pc();
+    // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
+    // Unix:  rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
+    const Register x      = rdi;
+    const Register len    = rsi;
+    const Register z      = r8;
+    const Register zlen   = rcx;
+
+   const Register tmp1      = r12;
+   const Register tmp2      = r13;
+   const Register tmp3      = r14;
+   const Register tmp4      = r15;
+   const Register tmp5      = rbx;
+
+    BLOCK_COMMENT("Entry:");
+    __ enter(); // required for proper stackwalking of RuntimeStub frame
+
+       setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
+                          // zlen => rcx
+                          // r9 and r10 may be used to save non-volatile registers
+    __ movptr(r8, rdx);
+    __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
+
+    restore_arg_regs();
+
+    __ leave(); // required for proper stackwalking of RuntimeStub frame
+    __ ret(0);
+
+    return start;
+  }
+
+   /**
+   *  Arguments:
+   *
+   *  Input:
+   *    c_rarg0   - out address
+   *    c_rarg1   - in address
+   *    c_rarg2   - offset
+   *    c_rarg3   - len
+   * not Win64
+   *    c_rarg4   - k
+   * Win64
+   *    rsp+40    - k
+   */
+  address generate_mulAdd() {
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", "mulAdd");
+
+    address start = __ pc();
+    // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
+    // Unix:  rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
+    const Register out     = rdi;
+    const Register in      = rsi;
+    const Register offset  = r11;
+    const Register len     = rcx;
+    const Register k       = r8;
+
+    // Next registers will be saved on stack in mul_add().
+    const Register tmp1  = r12;
+    const Register tmp2  = r13;
+    const Register tmp3  = r14;
+    const Register tmp4  = r15;
+    const Register tmp5  = rbx;
+
+    BLOCK_COMMENT("Entry:");
+    __ enter(); // required for proper stackwalking of RuntimeStub frame
+
+    setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
+                       // len => rcx, k => r8
+                       // r9 and r10 may be used to save non-volatile registers
+#ifdef _WIN64
+    // last argument is on stack on Win64
+    __ movl(k, Address(rsp, 6 * wordSize));
+#endif
+    __ movptr(r11, rdx);  // move offset in rdx to offset(r11)
+    __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
+
+    restore_arg_regs();
+
+    __ leave(); // required for proper stackwalking of RuntimeStub frame
+    __ ret(0);
+
+    return start;
+  }
+
+
 #undef __
 #define __ masm->
 
@@ -3987,7 +4088,24 @@
     if (UseMultiplyToLenIntrinsic) {
       StubRoutines::_multiplyToLen = generate_multiplyToLen();
     }
-#endif
+    if (UseSquareToLenIntrinsic) {
+      StubRoutines::_squareToLen = generate_squareToLen();
+    }
+    if (UseMulAddIntrinsic) {
+      StubRoutines::_mulAdd = generate_mulAdd();
+    }
+
+#ifndef _WINDOWS
+    if (UseMontgomeryMultiplyIntrinsic) {
+      StubRoutines::_montgomeryMultiply
+        = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_multiply);
+    }
+    if (UseMontgomerySquareIntrinsic) {
+      StubRoutines::_montgomerySquare
+        = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_square);
+    }
+#endif // WINDOWS
+#endif // COMPILER2
   }
 
  public:
diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp
index 205bce4..15922b8 100644
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp
@@ -33,7 +33,7 @@
 
 enum platform_dependent_constants {
   code_size1 = 19000,          // simply increase if too small (assembler will crash if too small)
-  code_size2 = 22000           // simply increase if too small (assembler will crash if too small)
+  code_size2 = 23000           // simply increase if too small (assembler will crash if too small)
 };
 
 class x86 {
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
index adfdfd6..28aa48e 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
@@ -703,6 +703,18 @@
   if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
     UseMultiplyToLenIntrinsic = true;
   }
+  if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
+    UseSquareToLenIntrinsic = false;
+  }
+  if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
+    UseMulAddIntrinsic = false;
+  }
+  if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
+    UseMontgomeryMultiplyIntrinsic = false;
+  }
+  if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
+    UseMontgomerySquareIntrinsic = false;
+  }
 #else
   if (UseMultiplyToLenIntrinsic) {
     if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
@@ -710,6 +722,30 @@
     }
     FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
   }
+  if (UseSquareToLenIntrinsic) {
+    if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
+      warning("squareToLen intrinsic is not available in 32-bit VM");
+    }
+    FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false);
+  }
+  if (UseMulAddIntrinsic) {
+    if (!FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
+      warning("mulAdd intrinsic is not available in 32-bit VM");
+    }
+    FLAG_SET_DEFAULT(UseMulAddIntrinsic, false);
+  }
+  if (UseMontgomeryMultiplyIntrinsic) {
+    if (!FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
+      warning("montgomeryMultiply intrinsic is not available in 32-bit VM");
+    }
+    FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false);
+  }
+  if (UseMontgomerySquareIntrinsic) {
+    if (!FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
+      warning("montgomerySquare intrinsic is not available in 32-bit VM");
+    }
+    FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false);
+  }
 #endif
 #endif // COMPILER2
 
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index 222d2b0..b857cb3 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -793,10 +793,26 @@
    do_signature(encodeISOArray_signature,                        "([CI[BII)I")                                          \
                                                                                                                         \
   do_class(java_math_BigInteger,                      "java/math/BigInteger")                                           \
-  do_intrinsic(_multiplyToLen,      java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_R)             \
+  do_intrinsic(_multiplyToLen,      java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S)             \
    do_name(     multiplyToLen_name,                             "multiplyToLen")                                        \
    do_signature(multiplyToLen_signature,                        "([II[II[I)[I")                                         \
                                                                                                                         \
+  do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S)                        \
+   do_name(     squareToLen_name,                             "implSquareToLen")                                        \
+   do_signature(squareToLen_signature,                        "([II[II)[I")                                             \
+                                                                                                                        \
+  do_intrinsic(_mulAdd, java_math_BigInteger, mulAdd_name, mulAdd_signature, F_S)                                       \
+   do_name(     mulAdd_name,                                  "implMulAdd")                                             \
+   do_signature(mulAdd_signature,                             "([I[IIII)I")                                             \
+                                                                                                                        \
+  do_intrinsic(_montgomeryMultiply,      java_math_BigInteger, montgomeryMultiply_name, montgomeryMultiply_signature, F_S) \
+   do_name(     montgomeryMultiply_name,                             "implMontgomeryMultiply")                          \
+   do_signature(montgomeryMultiply_signature,                        "([I[I[IIJ[I)[I")                                  \
+                                                                                                                        \
+  do_intrinsic(_montgomerySquare,      java_math_BigInteger, montgomerySquare_name, montgomerySquare_signature, F_S)    \
+   do_name(     montgomerySquare_name,                             "implMontgomerySquare")                              \
+   do_signature(montgomerySquare_signature,                        "([I[IIJ[I)[I")                                      \
+                                                                                                                        \
   /* java/lang/ref/Reference */                                                                                         \
   do_intrinsic(_Reference_get,            java_lang_ref_Reference, get_name,    void_object_signature, F_R)             \
                                                                                                                         \
diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp
index fe1834b..3aab433 100644
--- a/hotspot/src/share/vm/opto/c2_globals.hpp
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp
@@ -662,6 +662,18 @@
   product(bool, UseMultiplyToLenIntrinsic, false,                           \
           "Enables intrinsification of BigInteger.multiplyToLen()")         \
                                                                             \
+  product(bool, UseSquareToLenIntrinsic, false,                             \
+          "Enables intrinsification of BigInteger.squareToLen()")           \
+                                                                            \
+  product(bool, UseMulAddIntrinsic, false,                                  \
+          "Enables intrinsification of BigInteger.mulAdd()")                \
+                                                                            \
+  product(bool, UseMontgomeryMultiplyIntrinsic, false,                      \
+          "Enables intrinsification of BigInteger.montgomeryMultiply()")    \
+                                                                            \
+  product(bool, UseMontgomerySquareIntrinsic, false,                        \
+          "Enables intrinsification of BigInteger.montgomerySquare()")      \
+                                                                            \
   product(bool, UseTypeSpeculation, true,                                   \
           "Speculatively propagate types from profiles")                    \
                                                                             \
diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp
index 9473a62..b422215 100644
--- a/hotspot/src/share/vm/opto/compile.cpp
+++ b/hotspot/src/share/vm/opto/compile.cpp
@@ -412,6 +412,13 @@
       remove_macro_node(n);
     }
   }
+  // Remove useless CastII nodes with range check dependency
+  for (int i = range_check_cast_count() - 1; i >= 0; i--) {
+    Node* cast = range_check_cast_node(i);
+    if (!useful.member(cast)) {
+      remove_range_check_cast(cast);
+    }
+  }
   // Remove useless expensive node
   for (int i = C->expensive_count()-1; i >= 0; i--) {
     Node* n = C->expensive_node(i);
@@ -1148,6 +1155,7 @@
   _macro_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8,  0, NULL);
   _predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8,  0, NULL);
   _expensive_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8,  0, NULL);
+  _range_check_casts = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8,  0, NULL);
   register_library_intrinsics();
 }
 
@@ -1876,6 +1884,22 @@
   assert(predicate_count()==0, "should be clean!");
 }
 
+void Compile::add_range_check_cast(Node* n) {
+  assert(n->isa_CastII()->has_range_check(), "CastII should have range check dependency");
+  assert(!_range_check_casts->contains(n), "duplicate entry in range check casts");
+  _range_check_casts->append(n);
+}
+
+// Remove all range check dependent CastIINodes.
+void Compile::remove_range_check_casts(PhaseIterGVN &igvn) {
+  for (int i = range_check_cast_count(); i > 0; i--) {
+    Node* cast = range_check_cast_node(i-1);
+    assert(cast->isa_CastII()->has_range_check(), "CastII should have range check dependency");
+    igvn.replace_node(cast, cast->in(1));
+  }
+  assert(range_check_cast_count() == 0, "should be empty");
+}
+
 // StringOpts and late inlining of string methods
 void Compile::inline_string_calls(bool parse_time) {
   {
@@ -2218,6 +2242,12 @@
     PhaseIdealLoop::verify(igvn);
   }
 
+  if (range_check_cast_count() > 0) {
+    // No more loop optimizations. Remove all range check dependent CastIINodes.
+    C->remove_range_check_casts(igvn);
+    igvn.optimize();
+  }
+
   {
     NOT_PRODUCT( TracePhase t2("macroExpand", &_t_macroExpand, TimeCompiler); )
     PhaseMacroExpand  mex(igvn);
@@ -2987,6 +3017,16 @@
 
 #endif
 
+#ifdef ASSERT
+  case Op_CastII:
+    // Verify that all range check dependent CastII nodes were removed.
+    if (n->isa_CastII()->has_range_check()) {
+      n->dump(3);
+      assert(false, "Range check dependent CastII node was not removed");
+    }
+    break;
+#endif
+
   case Op_ModI:
     if (UseDivMod) {
       // Check if a%b and a/b both exist
@@ -4024,6 +4064,24 @@
   }
 }
 
+// Convert integer value to a narrowed long type dependent on ctrl (for example, a range check)
+Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl) {
+  if (ctrl != NULL) {
+    // Express control dependency by a CastII node with a narrow type.
+    value = new (phase->C) CastIINode(value, itype, false, true /* range check dependency */);
+    // Make the CastII node dependent on the control input to prevent the narrowed ConvI2L
+    // node from floating above the range check during loop optimizations. Otherwise, the
+    // ConvI2L node may be eliminated independently of the range check, causing the data path
+    // to become TOP while the control path is still there (although it's unreachable).
+    value->set_req(0, ctrl);
+    // Save CastII node to remove it after loop optimizations.
+    phase->C->add_range_check_cast(value);
+    value = phase->transform(value);
+  }
+  const TypeLong* ltype = TypeLong::make(itype->_lo, itype->_hi, itype->_widen);
+  return phase->transform(new (phase->C) ConvI2LNode(value, ltype));
+}
+
 // Auxiliary method to support randomized stressing/fuzzing.
 //
 // This method can be called the arbitrary number of times, with current count
diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp
index 570c99e..34028fc 100644
--- a/hotspot/src/share/vm/opto/compile.hpp
+++ b/hotspot/src/share/vm/opto/compile.hpp
@@ -75,6 +75,7 @@
 class JVMState;
 class Type;
 class TypeData;
+class TypeInt;
 class TypePtr;
 class TypeOopPtr;
 class TypeFunc;
@@ -334,6 +335,7 @@
   GrowableArray<Node*>* _macro_nodes;           // List of nodes which need to be expanded before matching.
   GrowableArray<Node*>* _predicate_opaqs;       // List of Opaque1 nodes for the loop predicates.
   GrowableArray<Node*>* _expensive_nodes;       // List of nodes that are expensive to compute and that we'd better not let the GVN freely common
+  GrowableArray<Node*>* _range_check_casts;     // List of CastII nodes with a range check dependency
   ConnectionGraph*      _congraph;
 #ifndef PRODUCT
   IdealGraphPrinter*    _printer;
@@ -669,7 +671,7 @@
   void set_congraph(ConnectionGraph* congraph)  { _congraph = congraph;}
   void add_macro_node(Node * n) {
     //assert(n->is_macro(), "must be a macro node");
-    assert(!_macro_nodes->contains(n), " duplicate entry in expand list");
+    assert(!_macro_nodes->contains(n), "duplicate entry in expand list");
     _macro_nodes->append(n);
   }
   void remove_macro_node(Node * n) {
@@ -689,10 +691,23 @@
     }
   }
   void add_predicate_opaq(Node * n) {
-    assert(!_predicate_opaqs->contains(n), " duplicate entry in predicate opaque1");
+    assert(!_predicate_opaqs->contains(n), "duplicate entry in predicate opaque1");
     assert(_macro_nodes->contains(n), "should have already been in macro list");
     _predicate_opaqs->append(n);
   }
+
+  // Range check dependent CastII nodes that can be removed after loop optimizations
+  void add_range_check_cast(Node* n);
+  void remove_range_check_cast(Node* n) {
+    if (_range_check_casts->contains(n)) {
+      _range_check_casts->remove(n);
+    }
+  }
+  Node* range_check_cast_node(int idx) const { return _range_check_casts->at(idx);  }
+  int   range_check_cast_count()       const { return _range_check_casts->length(); }
+  // Remove all range check dependent CastIINodes.
+  void  remove_range_check_casts(PhaseIterGVN &igvn);
+
   // remove the opaque nodes that protect the predicates so that the unused checks and
   // uncommon traps will be eliminated from the graph.
   void cleanup_loop_predicates(PhaseIterGVN &igvn);
@@ -1201,6 +1216,9 @@
   // Definitions of pd methods
   static void pd_compiler2_init();
 
+  // Convert integer value to a narrowed long type dependent on ctrl (for example, a range check)
+  static Node* constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl);
+
   // Auxiliary method for randomized fuzzing/stressing
   static bool randomized_select(int count);
 };
diff --git a/hotspot/src/share/vm/opto/connode.cpp b/hotspot/src/share/vm/opto/connode.cpp
index bfebd1c..00aee51 100644
--- a/hotspot/src/share/vm/opto/connode.cpp
+++ b/hotspot/src/share/vm/opto/connode.cpp
@@ -535,6 +535,9 @@
   if (_carry_dependency) {
     st->print(" carry dependency");
   }
+  if (_range_check_dependency) {
+    st->print(" range check dependency");
+  }
 }
 #endif
 
@@ -994,7 +997,8 @@
   }
 
 #ifdef _LP64
-  // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) ,
+  // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) or
+  // ConvI2L(CastII(AddI(x, y))) to AddL(ConvI2L(CastII(x)), ConvI2L(CastII(y))),
   // but only if x and y have subranges that cannot cause 32-bit overflow,
   // under the assumption that x+y is in my own subrange this->type().
 
@@ -1018,6 +1022,13 @@
 
   Node* z = in(1);
   int op = z->Opcode();
+  Node* ctrl = NULL;
+  if (op == Op_CastII && z->as_CastII()->has_range_check()) {
+    // Skip CastII node but save control dependency
+    ctrl = z->in(0);
+    z = z->in(1);
+    op = z->Opcode();
+  }
   if (op == Op_AddI || op == Op_SubI) {
     Node* x = z->in(1);
     Node* y = z->in(2);
@@ -1075,9 +1086,10 @@
       rylo = -ryhi;
       ryhi = -rylo0;
     }
-
-    Node* cx = phase->transform( new (phase->C) ConvI2LNode(x, TypeLong::make(rxlo, rxhi, widen)) );
-    Node* cy = phase->transform( new (phase->C) ConvI2LNode(y, TypeLong::make(rylo, ryhi, widen)) );
+    assert(rxlo == (int)rxlo && rxhi == (int)rxhi, "x should not overflow");
+    assert(rylo == (int)rylo && ryhi == (int)ryhi, "y should not overflow");
+    Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), ctrl);
+    Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), ctrl);
     switch (op) {
     case Op_AddI:  return new (phase->C) AddLNode(cx, cy);
     case Op_SubI:  return new (phase->C) SubLNode(cx, cy);
diff --git a/hotspot/src/share/vm/opto/connode.hpp b/hotspot/src/share/vm/opto/connode.hpp
index 5558028..21c2276 100644
--- a/hotspot/src/share/vm/opto/connode.hpp
+++ b/hotspot/src/share/vm/opto/connode.hpp
@@ -244,19 +244,31 @@
   private:
   // Can this node be removed post CCP or does it carry a required dependency?
   const bool _carry_dependency;
+  // Is this node dependent on a range check?
+  const bool _range_check_dependency;
 
   protected:
   virtual uint cmp( const Node &n ) const;
   virtual uint size_of() const;
 
 public:
-  CastIINode(Node *n, const Type *t, bool carry_dependency = false)
-    : ConstraintCastNode(n,t), _carry_dependency(carry_dependency) {}
+  CastIINode(Node *n, const Type *t, bool carry_dependency = false, bool range_check_dependency = false)
+    : ConstraintCastNode(n,t), _carry_dependency(carry_dependency), _range_check_dependency(range_check_dependency) {
+    init_class_id(Class_CastII);
+  }
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegI; }
   virtual Node *Identity( PhaseTransform *phase );
   virtual const Type *Value( PhaseTransform *phase ) const;
   virtual Node *Ideal_DU_postCCP( PhaseCCP * );
+  const bool has_range_check() {
+ #ifdef _LP64
+     return _range_check_dependency;
+ #else
+     assert(!_range_check_dependency, "Should not have range check dependency");
+     return false;
+ #endif
+   }
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
 #endif
diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp
index b5e1f6b..bcd2e78 100644
--- a/hotspot/src/share/vm/opto/escape.cpp
+++ b/hotspot/src/share/vm/opto/escape.cpp
@@ -958,8 +958,12 @@
                   strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 ||
-                  strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0)
-                  ))) {
+                  strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "squareToLen") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "mulAdd") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "montgomery_multiply") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "montgomery_square") == 0)
+                 ))) {
             call->dump();
             fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
           }
diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp
index 4300aae..38e0ce2 100644
--- a/hotspot/src/share/vm/opto/graphKit.cpp
+++ b/hotspot/src/share/vm/opto/graphKit.cpp
@@ -1645,7 +1645,7 @@
 
 //-------------------------array_element_address-------------------------
 Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt,
-                                      const TypeInt* sizetype) {
+                                      const TypeInt* sizetype, Node* ctrl) {
   uint shift  = exact_log2(type2aelembytes(elembt));
   uint header = arrayOopDesc::base_offset_in_bytes(elembt);
 
@@ -1670,9 +1670,9 @@
   // number.  (The prior range check has ensured this.)
   // This assertion is used by ConvI2LNode::Ideal.
   int index_max = max_jint - 1;  // array size is max_jint, index is one less
-  if (sizetype != NULL)  index_max = sizetype->_hi - 1;
-  const TypeLong* lidxtype = TypeLong::make(CONST64(0), index_max, Type::WidenMax);
-  idx = _gvn.transform( new (C) ConvI2LNode(idx, lidxtype) );
+  if (sizetype != NULL) index_max = sizetype->_hi - 1;
+  const TypeInt* iidxtype = TypeInt::make(0, index_max, Type::WidenMax);
+  idx = C->constrained_convI2L(&_gvn, idx, iidxtype, ctrl);
 #endif
   Node* scale = _gvn.transform( new (C) LShiftXNode(idx, intcon(shift)) );
   return basic_plus_adr(ary, base, scale);
@@ -3491,10 +3491,6 @@
 
   Node* initial_slow_cmp  = _gvn.transform( new (C) CmpUNode( length, intcon( fast_size_limit ) ) );
   Node* initial_slow_test = _gvn.transform( new (C) BoolNode( initial_slow_cmp, BoolTest::gt ) );
-  if (initial_slow_test->is_Bool()) {
-    // Hide it behind a CMoveI, or else PhaseIdealLoop::split_up will get sick.
-    initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn);
-  }
 
   // --- Size Computation ---
   // array_size = round_to_heap(array_header + (length << elem_shift));
@@ -3540,13 +3536,35 @@
   Node* lengthx = ConvI2X(length);
   Node* headerx = ConvI2X(header_size);
 #ifdef _LP64
-  { const TypeLong* tllen = _gvn.find_long_type(lengthx);
-    if (tllen != NULL && tllen->_lo < 0) {
+  { const TypeInt* tilen = _gvn.find_int_type(length);
+    if (tilen != NULL && tilen->_lo < 0) {
       // Add a manual constraint to a positive range.  Cf. array_element_address.
-      jlong size_max = arrayOopDesc::max_array_length(T_BYTE);
-      if (size_max > tllen->_hi)  size_max = tllen->_hi;
-      const TypeLong* tlcon = TypeLong::make(CONST64(0), size_max, Type::WidenMin);
-      lengthx = _gvn.transform( new (C) ConvI2LNode(length, tlcon));
+      jlong size_max = fast_size_limit;
+      if (size_max > tilen->_hi)  size_max = tilen->_hi;
+      const TypeInt* tlcon = TypeInt::make(0, size_max, Type::WidenMin);
+
+      // Only do a narrow I2L conversion if the range check passed.
+      IfNode* iff = new (C) IfNode(control(), initial_slow_test, PROB_MIN, COUNT_UNKNOWN);
+      _gvn.transform(iff);
+      RegionNode* region = new (C) RegionNode(3);
+      _gvn.set_type(region, Type::CONTROL);
+      lengthx = new (C) PhiNode(region, TypeLong::LONG);
+      _gvn.set_type(lengthx, TypeLong::LONG);
+
+      // Range check passed. Use ConvI2L node with narrow type.
+      Node* passed = IfFalse(iff);
+      region->init_req(1, passed);
+      // Make I2L conversion control dependent to prevent it from
+      // floating above the range check during loop optimizations.
+      lengthx->init_req(1, C->constrained_convI2L(&_gvn, length, tlcon, passed));
+
+      // Range check failed. Use ConvI2L with wide type because length may be invalid.
+      region->init_req(2, IfTrue(iff));
+      lengthx->init_req(2, ConvI2X(length));
+
+      set_control(region);
+      record_for_igvn(region);
+      record_for_igvn(lengthx);
     }
   }
 #endif
@@ -3577,6 +3595,11 @@
   Node *mem = reset_memory();
   set_all_memory(mem); // Create new memory state
 
+  if (initial_slow_test->is_Bool()) {
+    // Hide it behind a CMoveI, or else PhaseIdealLoop::split_up will get sick.
+    initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn);
+  }
+
   // Create the AllocateArrayNode and its result projections
   AllocateArrayNode* alloc
     = new (C) AllocateArrayNode(C, AllocateArrayNode::alloc_type(TypeInt::INT),
diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp
index a5437e7..d7c32b3 100644
--- a/hotspot/src/share/vm/opto/graphKit.hpp
+++ b/hotspot/src/share/vm/opto/graphKit.hpp
@@ -626,7 +626,9 @@
   // Return addressing for an array element.
   Node* array_element_address(Node* ary, Node* idx, BasicType elembt,
                               // Optional constraint on the array size:
-                              const TypeInt* sizetype = NULL);
+                              const TypeInt* sizetype = NULL,
+                              // Optional control dependency (for example, on range check)
+                              Node* ctrl = NULL);
 
   // Return a load of array element at idx.
   Node* load_array_element(Node* ctl, Node* ary, Node* idx, const TypeAryPtr* arytype);
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index b234d8b..243cf74 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -324,6 +324,10 @@
   bool inline_updateBytesCRC32();
   bool inline_updateByteBufferCRC32();
   bool inline_multiplyToLen();
+  bool inline_squareToLen();
+  bool inline_mulAdd();
+  bool inline_montgomeryMultiply();
+  bool inline_montgomerySquare();
 
   bool inline_profileBoolean();
 };
@@ -527,6 +531,21 @@
     if (!UseMultiplyToLenIntrinsic) return NULL;
     break;
 
+  case vmIntrinsics::_squareToLen:
+    if (!UseSquareToLenIntrinsic) return NULL;
+    break;
+
+  case vmIntrinsics::_mulAdd:
+    if (!UseMulAddIntrinsic) return NULL;
+    break;
+
+  case vmIntrinsics::_montgomeryMultiply:
+     if (!UseMontgomeryMultiplyIntrinsic) return NULL;
+    break;
+  case vmIntrinsics::_montgomerySquare:
+     if (!UseMontgomerySquareIntrinsic) return NULL;
+    break;
+
   case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
   case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
     if (!UseAESIntrinsics) return NULL;
@@ -927,6 +946,17 @@
   case vmIntrinsics::_multiplyToLen:
     return inline_multiplyToLen();
 
+  case vmIntrinsics::_squareToLen:
+    return inline_squareToLen();
+
+  case vmIntrinsics::_mulAdd:
+    return inline_mulAdd();
+
+  case vmIntrinsics::_montgomeryMultiply:
+    return inline_montgomeryMultiply();
+  case vmIntrinsics::_montgomerySquare:
+    return inline_montgomerySquare();
+
   case vmIntrinsics::_encodeISOArray:
     return inline_encodeISOArray();
 
@@ -5767,11 +5797,12 @@
 
   assert(callee()->signature()->size() == 5, "multiplyToLen has 5 parameters");
 
-  Node* x    = argument(1);
-  Node* xlen = argument(2);
-  Node* y    = argument(3);
-  Node* ylen = argument(4);
-  Node* z    = argument(5);
+  // no receiver because it is a static method
+  Node* x    = argument(0);
+  Node* xlen = argument(1);
+  Node* y    = argument(2);
+  Node* ylen = argument(3);
+  Node* z    = argument(4);
 
   const Type* x_type = x->Value(&_gvn);
   const Type* y_type = y->Value(&_gvn);
@@ -5856,6 +5887,215 @@
   return true;
 }
 
+//-------------inline_squareToLen------------------------------------
+bool LibraryCallKit::inline_squareToLen() {
+  assert(UseSquareToLenIntrinsic, "not implementated on this platform");
+
+  address stubAddr = StubRoutines::squareToLen();
+  if (stubAddr == NULL) {
+    return false; // Intrinsic's stub is not implemented on this platform
+  }
+  const char* stubName = "squareToLen";
+
+  assert(callee()->signature()->size() == 4, "implSquareToLen has 4 parameters");
+
+  Node* x    = argument(0);
+  Node* len  = argument(1);
+  Node* z    = argument(2);
+  Node* zlen = argument(3);
+
+  const Type* x_type = x->Value(&_gvn);
+  const Type* z_type = z->Value(&_gvn);
+  const TypeAryPtr* top_x = x_type->isa_aryptr();
+  const TypeAryPtr* top_z = z_type->isa_aryptr();
+  if (top_x  == NULL || top_x->klass()  == NULL ||
+      top_z  == NULL || top_z->klass()  == NULL) {
+    // failed array check
+    return false;
+  }
+
+  BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType z_elem = z_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (x_elem != T_INT || z_elem != T_INT) {
+    return false;
+  }
+
+
+  Node* x_start = array_element_address(x, intcon(0), x_elem);
+  Node* z_start = array_element_address(z, intcon(0), z_elem);
+
+  Node*  call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                                  OptoRuntime::squareToLen_Type(),
+                                  stubAddr, stubName, TypePtr::BOTTOM,
+                                  x_start, len, z_start, zlen);
+
+  set_result(z);
+  return true;
+}
+
+//-------------inline_mulAdd------------------------------------------
+bool LibraryCallKit::inline_mulAdd() {
+  assert(UseMulAddIntrinsic, "not implementated on this platform");
+
+  address stubAddr = StubRoutines::mulAdd();
+  if (stubAddr == NULL) {
+    return false; // Intrinsic's stub is not implemented on this platform
+  }
+  const char* stubName = "mulAdd";
+
+  assert(callee()->signature()->size() == 5, "mulAdd has 5 parameters");
+
+  Node* out      = argument(0);
+  Node* in       = argument(1);
+  Node* offset   = argument(2);
+  Node* len      = argument(3);
+  Node* k        = argument(4);
+
+  const Type* out_type = out->Value(&_gvn);
+  const Type* in_type = in->Value(&_gvn);
+  const TypeAryPtr* top_out = out_type->isa_aryptr();
+  const TypeAryPtr* top_in = in_type->isa_aryptr();
+  if (top_out  == NULL || top_out->klass()  == NULL ||
+      top_in == NULL || top_in->klass() == NULL) {
+    // failed array check
+    return false;
+  }
+
+  BasicType out_elem = out_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType in_elem = in_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (out_elem != T_INT || in_elem != T_INT) {
+    return false;
+  }
+
+  Node* outlen = load_array_length(out);
+  Node* new_offset = _gvn.transform(new (C) SubINode(outlen, offset));
+  Node* out_start = array_element_address(out, intcon(0), out_elem);
+  Node* in_start = array_element_address(in, intcon(0), in_elem);
+
+  Node*  call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                                  OptoRuntime::mulAdd_Type(),
+                                  stubAddr, stubName, TypePtr::BOTTOM,
+                                  out_start,in_start, new_offset, len, k);
+  Node* result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms));
+  set_result(result);
+  return true;
+}
+
+//-------------inline_montgomeryMultiply-----------------------------------
+bool LibraryCallKit::inline_montgomeryMultiply() {
+  address stubAddr = StubRoutines::montgomeryMultiply();
+  if (stubAddr == NULL) {
+    return false; // Intrinsic's stub is not implemented on this platform
+  }
+
+  assert(UseMontgomeryMultiplyIntrinsic, "not implemented on this platform");
+  const char* stubName = "montgomery_square";
+
+  assert(callee()->signature()->size() == 7, "montgomeryMultiply has 7 parameters");
+
+  Node* a    = argument(0);
+  Node* b    = argument(1);
+  Node* n    = argument(2);
+  Node* len  = argument(3);
+  Node* inv  = argument(4);
+  Node* m    = argument(6);
+
+  const Type* a_type = a->Value(&_gvn);
+  const TypeAryPtr* top_a = a_type->isa_aryptr();
+  const Type* b_type = b->Value(&_gvn);
+  const TypeAryPtr* top_b = b_type->isa_aryptr();
+  const Type* n_type = a->Value(&_gvn);
+  const TypeAryPtr* top_n = n_type->isa_aryptr();
+  const Type* m_type = a->Value(&_gvn);
+  const TypeAryPtr* top_m = m_type->isa_aryptr();
+  if (top_a  == NULL || top_a->klass()  == NULL ||
+      top_b == NULL || top_b->klass()  == NULL ||
+      top_n == NULL || top_n->klass()  == NULL ||
+      top_m == NULL || top_m->klass()  == NULL) {
+    // failed array check
+    return false;
+  }
+
+  BasicType a_elem = a_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType b_elem = b_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType n_elem = n_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType m_elem = m_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (a_elem != T_INT || b_elem != T_INT || n_elem != T_INT || m_elem != T_INT) {
+    return false;
+  }
+
+  // Make the call
+  {
+    Node* a_start = array_element_address(a, intcon(0), a_elem);
+    Node* b_start = array_element_address(b, intcon(0), b_elem);
+    Node* n_start = array_element_address(n, intcon(0), n_elem);
+    Node* m_start = array_element_address(m, intcon(0), m_elem);
+
+    Node* call = make_runtime_call(RC_LEAF,
+                                   OptoRuntime::montgomeryMultiply_Type(),
+                                   stubAddr, stubName, TypePtr::BOTTOM,
+                                   a_start, b_start, n_start, len, inv, top(),
+                                   m_start);
+    set_result(m);
+  }
+
+  return true;
+}
+
+bool LibraryCallKit::inline_montgomerySquare() {
+  address stubAddr = StubRoutines::montgomerySquare();
+  if (stubAddr == NULL) {
+    return false; // Intrinsic's stub is not implemented on this platform
+  }
+
+  assert(UseMontgomerySquareIntrinsic, "not implemented on this platform");
+  const char* stubName = "montgomery_square";
+
+  assert(callee()->signature()->size() == 6, "montgomerySquare has 6 parameters");
+
+  Node* a    = argument(0);
+  Node* n    = argument(1);
+  Node* len  = argument(2);
+  Node* inv  = argument(3);
+  Node* m    = argument(5);
+
+  const Type* a_type = a->Value(&_gvn);
+  const TypeAryPtr* top_a = a_type->isa_aryptr();
+  const Type* n_type = a->Value(&_gvn);
+  const TypeAryPtr* top_n = n_type->isa_aryptr();
+  const Type* m_type = a->Value(&_gvn);
+  const TypeAryPtr* top_m = m_type->isa_aryptr();
+  if (top_a  == NULL || top_a->klass()  == NULL ||
+      top_n == NULL || top_n->klass()  == NULL ||
+      top_m == NULL || top_m->klass()  == NULL) {
+    // failed array check
+    return false;
+  }
+
+  BasicType a_elem = a_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType n_elem = n_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType m_elem = m_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (a_elem != T_INT || n_elem != T_INT || m_elem != T_INT) {
+    return false;
+  }
+
+  // Make the call
+  {
+    Node* a_start = array_element_address(a, intcon(0), a_elem);
+    Node* n_start = array_element_address(n, intcon(0), n_elem);
+    Node* m_start = array_element_address(m, intcon(0), m_elem);
+
+    Node* call = make_runtime_call(RC_LEAF,
+                                   OptoRuntime::montgomerySquare_Type(),
+                                   stubAddr, stubName, TypePtr::BOTTOM,
+                                   a_start, n_start, len, inv, top(),
+                                   m_start);
+    set_result(m);
+  }
+
+  return true;
+}
+
 
 /**
  * Calculate CRC32 for byte.
diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp
index a6a7ab0..171032d 100644
--- a/hotspot/src/share/vm/opto/loopTransform.cpp
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp
@@ -2438,7 +2438,7 @@
 
 //=============================================================================
 // Process all the loops in the loop tree and replace any fill
-// patterns with an intrisc version.
+// patterns with an intrinsic version.
 bool PhaseIdealLoop::do_intrinsify_fill() {
   bool changed = false;
   for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
@@ -2536,8 +2536,9 @@
   }
 
   // Make sure the address expression can be handled.  It should be
-  // head->phi * elsize + con.  head->phi might have a ConvI2L.
+  // head->phi * elsize + con.  head->phi might have a ConvI2L(CastII()).
   Node* elements[4];
+  Node* cast = NULL;
   Node* conv = NULL;
   bool found_index = false;
   int count = store->in(MemNode::Address)->as_AddP()->unpack_offsets(elements, ARRAY_SIZE(elements));
@@ -2552,6 +2553,12 @@
         conv = value;
         value = value->in(1);
       }
+      if (value->Opcode() == Op_CastII &&
+          value->as_CastII()->has_range_check()) {
+        // Skip range check dependent CastII nodes
+        cast = value;
+        value = value->in(1);
+      }
 #endif
       if (value != head->phi()) {
         msg = "unhandled shift in address";
@@ -2564,9 +2571,16 @@
         }
       }
     } else if (n->Opcode() == Op_ConvI2L && conv == NULL) {
-      if (n->in(1) == head->phi()) {
+      conv = n;
+      n = n->in(1);
+      if (n->Opcode() == Op_CastII &&
+          n->as_CastII()->has_range_check()) {
+        // Skip range check dependent CastII nodes
+        cast = n;
+        n = n->in(1);
+      }
+      if (n == head->phi()) {
         found_index = true;
-        conv = n;
       } else {
         msg = "unhandled input to ConvI2L";
       }
@@ -2625,6 +2639,7 @@
   // Address elements are ok
   if (con)   ok.set(con->_idx);
   if (shift) ok.set(shift->_idx);
+  if (cast)  ok.set(cast->_idx);
   if (conv)  ok.set(conv->_idx);
 
   for (uint i = 0; msg == NULL && i < lpt->_body.size(); i++) {
diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp
index 217effd..062daec 100644
--- a/hotspot/src/share/vm/opto/loopopts.cpp
+++ b/hotspot/src/share/vm/opto/loopopts.cpp
@@ -772,6 +772,9 @@
 #ifdef _LP64
         if (m->Opcode() == Op_ConvI2L)
           return false;
+        if (m->is_CastII() && m->isa_CastII()->has_range_check()) {
+          return false;
+        }
 #endif
       }
     }
diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp
index 26435b9..c4f6c16 100644
--- a/hotspot/src/share/vm/opto/node.cpp
+++ b/hotspot/src/share/vm/opto/node.cpp
@@ -521,6 +521,11 @@
     C->add_macro_node(n);
   if (is_expensive())
     C->add_expensive_node(n);
+  // If the cloned node is a range check dependent CastII, add it to the list.
+  CastIINode* cast = n->isa_CastII();
+  if (cast != NULL && cast->has_range_check()) {
+    C->add_range_check_cast(cast);
+  }
 
   n->set_idx(C->next_unique()); // Get new unique index as well
   debug_only( n->verify_construction() );
@@ -649,6 +654,11 @@
   if (is_expensive()) {
     compile->remove_expensive_node(this);
   }
+  CastIINode* cast = isa_CastII();
+  if (cast != NULL && cast->has_range_check()) {
+    compile->remove_range_check_cast(cast);
+  }
+
   if (is_SafePoint()) {
     as_SafePoint()->delete_replaced_nodes();
   }
@@ -1344,6 +1354,10 @@
       if (dead->is_expensive()) {
         igvn->C->remove_expensive_node(dead);
       }
+      CastIINode* cast = dead->isa_CastII();
+      if (cast != NULL && cast->has_range_check()) {
+        igvn->C->remove_range_check_cast(cast);
+      }
       igvn->C->record_dead_node(dead->_idx);
       // Kill all inputs to the dead guy
       for (uint i=0; i < dead->req(); i++) {
diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp
index ffb096e..cba8fa8 100644
--- a/hotspot/src/share/vm/opto/node.hpp
+++ b/hotspot/src/share/vm/opto/node.hpp
@@ -54,6 +54,7 @@
 class CatchNode;
 class CatchProjNode;
 class CheckCastPPNode;
+class CastIINode;
 class ClearArrayNode;
 class CmpNode;
 class CodeBuffer;
@@ -603,6 +604,7 @@
     DEFINE_CLASS_ID(Type,  Node, 2)
       DEFINE_CLASS_ID(Phi,   Type, 0)
       DEFINE_CLASS_ID(ConstraintCast, Type, 1)
+        DEFINE_CLASS_ID(CastII, ConstraintCast, 0)
       DEFINE_CLASS_ID(CheckCastPP, Type, 2)
       DEFINE_CLASS_ID(CMove, Type, 3)
       DEFINE_CLASS_ID(SafePointScalarObject, Type, 4)
@@ -727,6 +729,7 @@
   DEFINE_CLASS_QUERY(Catch)
   DEFINE_CLASS_QUERY(CatchProj)
   DEFINE_CLASS_QUERY(CheckCastPP)
+  DEFINE_CLASS_QUERY(CastII)
   DEFINE_CLASS_QUERY(ConstraintCast)
   DEFINE_CLASS_QUERY(ClearArray)
   DEFINE_CLASS_QUERY(CMove)
diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp
index 71837d8..8bdd5b5 100644
--- a/hotspot/src/share/vm/opto/parse2.cpp
+++ b/hotspot/src/share/vm/opto/parse2.cpp
@@ -158,7 +158,9 @@
   // Check for always knowing you are throwing a range-check exception
   if (stopped())  return top();
 
-  Node* ptr = array_element_address(ary, idx, type, sizetype);
+  // Make array address computation control dependent to prevent it
+  // from floating above the range check during loop optimizations.
+  Node* ptr = array_element_address(ary, idx, type, sizetype, control());
 
   if (result2 != NULL)  *result2 = elemtype;
 
@@ -461,9 +463,12 @@
 #ifdef _LP64
   // Clean the 32-bit int into a real 64-bit offset.
   // Otherwise, the jint value 0 might turn into an offset of 0x0800000000.
-  const TypeLong* lkeytype = TypeLong::make(CONST64(0), num_cases-1, Type::WidenMin);
-  key_val       = _gvn.transform( new (C) ConvI2LNode(key_val, lkeytype) );
+  const TypeInt* ikeytype = TypeInt::make(0, num_cases-1, Type::WidenMin);
+  // Make I2L conversion control dependent to prevent it from
+  // floating above the range check during loop optimizations.
+  key_val = C->constrained_convI2L(&_gvn, key_val, ikeytype, control());
 #endif
+
   // Shift the value by wordsize so we have an index into the table, rather
   // than a switch value
   Node *shiftWord = _gvn.MakeConX(wordSize);
diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp
index 2c42f9a..f090fcc 100644
--- a/hotspot/src/share/vm/opto/phaseX.cpp
+++ b/hotspot/src/share/vm/opto/phaseX.cpp
@@ -1339,6 +1339,10 @@
       if (dead->is_expensive()) {
         C->remove_expensive_node(dead);
       }
+      CastIINode* cast = dead->isa_CastII();
+      if (cast != NULL && cast->has_range_check()) {
+        C->remove_range_check_cast(cast);
+      }
     }
   } // while (_stack.is_nonempty())
 }
diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp
index 2b62a99..861f599 100644
--- a/hotspot/src/share/vm/opto/runtime.cpp
+++ b/hotspot/src/share/vm/opto/runtime.cpp
@@ -956,6 +956,94 @@
   return TypeFunc::make(domain, range);
 }
 
+const TypeFunc* OptoRuntime::squareToLen_Type() {
+  // create input type (domain)
+  int num_args      = 4;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypePtr::NOTNULL;    // x
+  fields[argp++] = TypeInt::INT;        // len
+  fields[argp++] = TypePtr::NOTNULL;    // z
+  fields[argp++] = TypeInt::INT;        // zlen
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // no result type needed
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = NULL;
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
+  return TypeFunc::make(domain, range);
+}
+
+// for mulAdd calls, 2 pointers and 3 ints, returning int
+const TypeFunc* OptoRuntime::mulAdd_Type() {
+  // create input type (domain)
+  int num_args      = 5;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypePtr::NOTNULL;    // out
+  fields[argp++] = TypePtr::NOTNULL;    // in
+  fields[argp++] = TypeInt::INT;        // offset
+  fields[argp++] = TypeInt::INT;        // len
+  fields[argp++] = TypeInt::INT;        // k
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // returning carry (int)
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = TypeInt::INT;
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
+  return TypeFunc::make(domain, range);
+}
+
+const TypeFunc* OptoRuntime::montgomeryMultiply_Type() {
+  // create input type (domain)
+  int num_args      = 7;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypePtr::NOTNULL;    // a
+  fields[argp++] = TypePtr::NOTNULL;    // b
+  fields[argp++] = TypePtr::NOTNULL;    // n
+  fields[argp++] = TypeInt::INT;        // len
+  fields[argp++] = TypeLong::LONG;      // inv
+  fields[argp++] = Type::HALF;
+  fields[argp++] = TypePtr::NOTNULL;    // result
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // result type needed
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = TypePtr::NOTNULL;
+
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
+  return TypeFunc::make(domain, range);
+}
+
+const TypeFunc* OptoRuntime::montgomerySquare_Type() {
+  // create input type (domain)
+  int num_args      = 6;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypePtr::NOTNULL;    // a
+  fields[argp++] = TypePtr::NOTNULL;    // n
+  fields[argp++] = TypeInt::INT;        // len
+  fields[argp++] = TypeLong::LONG;      // inv
+  fields[argp++] = Type::HALF;
+  fields[argp++] = TypePtr::NOTNULL;    // result
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // result type needed
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = TypePtr::NOTNULL;
+
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
+  return TypeFunc::make(domain, range);
+}
 
 
 //------------- Interpreter state access for on stack replacement
diff --git a/hotspot/src/share/vm/opto/runtime.hpp b/hotspot/src/share/vm/opto/runtime.hpp
index 3258c36..99f03f4 100644
--- a/hotspot/src/share/vm/opto/runtime.hpp
+++ b/hotspot/src/share/vm/opto/runtime.hpp
@@ -305,6 +305,12 @@
 
   static const TypeFunc* multiplyToLen_Type();
 
+  static const TypeFunc* squareToLen_Type();
+
+  static const TypeFunc* mulAdd_Type();
+  static const TypeFunc* montgomeryMultiply_Type();
+  static const TypeFunc* montgomerySquare_Type();
+
   static const TypeFunc* updateBytesCRC32_Type();
 
   // leaf on stack replacement interpreter accessor types
diff --git a/hotspot/src/share/vm/opto/superword.cpp b/hotspot/src/share/vm/opto/superword.cpp
index 785b8bb..f005ef4 100644
--- a/hotspot/src/share/vm/opto/superword.cpp
+++ b/hotspot/src/share/vm/opto/superword.cpp
@@ -2388,6 +2388,11 @@
       return true;
     }
   } else if (opc == Op_ConvI2L) {
+    if (n->in(1)->Opcode() == Op_CastII &&
+        n->in(1)->as_CastII()->has_range_check()) {
+      // Skip range check dependent CastII nodes
+      n = n->in(1);
+    }
     if (scaled_iv_plus_offset(n->in(1))) {
       return true;
     }
diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp
index 17b0e03..2167eb8 100644
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp
@@ -145,6 +145,12 @@
   static double dsqrt(double f);
 #endif
 
+  // Montgomery multiplication
+  static void montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints,
+                                  jint len, jlong inv, jint *m_ints);
+  static void montgomery_square(jint *a_ints, jint *n_ints,
+                                jint len, jlong inv, jint *m_ints);
+
 #ifdef __SOFTFP__
   // C++ compiler generates soft float instructions as well as passing
   // float and double in registers.
diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp
index f35cce9..eb30640 100644
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp
@@ -136,6 +136,10 @@
 address StubRoutines::_crc_table_adr = NULL;
 
 address StubRoutines::_multiplyToLen = NULL;
+address StubRoutines::_squareToLen = NULL;
+address StubRoutines::_mulAdd = NULL;
+address StubRoutines::_montgomeryMultiply = NULL;
+address StubRoutines::_montgomerySquare = NULL;
 
 double (* StubRoutines::_intrinsic_log   )(double) = NULL;
 double (* StubRoutines::_intrinsic_log10 )(double) = NULL;
diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp
index 819b9c4..42808a4 100644
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp
@@ -209,6 +209,10 @@
   static address _crc_table_adr;
 
   static address _multiplyToLen;
+  static address _squareToLen;
+  static address _mulAdd;
+  static address _montgomeryMultiply;
+  static address _montgomerySquare;
 
   // These are versions of the java.lang.Math methods which perform
   // the same operations as the intrinsic version.  They are used for
@@ -367,6 +371,10 @@
   static address crc_table_addr()      { return _crc_table_adr; }
 
   static address multiplyToLen()       {return _multiplyToLen; }
+  static address squareToLen()         {return _squareToLen; }
+  static address mulAdd()              {return _mulAdd; }
+  static address montgomeryMultiply()  { return _montgomeryMultiply; }
+  static address montgomerySquare()    { return _montgomerySquare; }
 
   static address select_fill_function(BasicType t, bool aligned, const char* &name);
 
diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp
index f1200e3..80b0115 100644
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp
@@ -813,6 +813,8 @@
      static_field(StubRoutines,                _updateBytesCRC32,                             address)                               \
      static_field(StubRoutines,                _crc_table_adr,                                address)                               \
      static_field(StubRoutines,                _multiplyToLen,                                address)                               \
+     static_field(StubRoutines,                _squareToLen,                                  address)                               \
+     static_field(StubRoutines,                _mulAdd,                                       address)                               \
                                                                                                                                      \
   /*****************/                                                                                                                \
   /* SharedRuntime */                                                                                                                \
diff --git a/hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java b/hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java
new file mode 100644
index 0000000..5ddca7a
--- /dev/null
+++ b/hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java
@@ -0,0 +1,284 @@
+//
+// Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2015, Red Hat Inc. All rights reserved.
+// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+//
+// This code is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 2 only, as
+// published by the Free Software Foundation.
+//
+// This code is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// version 2 for more details (a copy is included in the LICENSE file that
+// accompanied this code).
+//
+// You should have received a copy of the GNU General Public License version
+// 2 along with this work; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+// or visit www.oracle.com if you need additional information or have any
+// questions.
+//
+//
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * @test
+ * @bug 8130150
+ * @library /testlibrary
+ * @requires (os.simpleArch == "x64") & (os.family != "windows")
+ * @summary Verify that the Montgomery multiply intrinsic works and correctly checks its arguments.
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMontgomerySquareIntrinsic
+ *      -XX:+UseMontgomeryMultiplyIntrinsic MontgomeryMultiplyTest
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMontgomerySquareIntrinsic
+ *      -XX:-UseMontgomeryMultiplyIntrinsic MontgomeryMultiplyTest
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseMontgomerySquareIntrinsic
+ *      -XX:+UseMontgomeryMultiplyIntrinsic MontgomeryMultiplyTest
+ */
+
+public class MontgomeryMultiplyTest {
+
+    static final MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+    static final MethodHandle montgomeryMultiplyHandle, montgomerySquareHandle;
+    static final MethodHandle bigIntegerConstructorHandle;
+    static final Field bigIntegerMagField;
+
+    static {
+       // Use reflection to gain access to the methods we want to test.
+        try {
+            Method m = BigInteger.class.getDeclaredMethod("montgomeryMultiply",
+                /*a*/int[].class, /*b*/int[].class, /*n*/int[].class, /*len*/int.class,
+                /*inv*/long.class, /*product*/int[].class);
+            m.setAccessible(true);
+            montgomeryMultiplyHandle = lookup.unreflect(m);
+
+            m = BigInteger.class.getDeclaredMethod("montgomerySquare",
+                /*a*/int[].class, /*n*/int[].class, /*len*/int.class,
+                /*inv*/long.class, /*product*/int[].class);
+            m.setAccessible(true);
+            montgomerySquareHandle = lookup.unreflect(m);
+
+            Constructor c
+                = BigInteger.class.getDeclaredConstructor(int.class, int[].class);
+            c.setAccessible(true);
+            bigIntegerConstructorHandle = lookup.unreflectConstructor(c);
+
+            bigIntegerMagField = BigInteger.class.getDeclaredField("mag");
+            bigIntegerMagField.setAccessible(true);
+
+        } catch (Throwable ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    // Invoke either BigInteger.montgomeryMultiply or BigInteger.montgomerySquare.
+    int[] montgomeryMultiply(int[] a, int[] b, int[] n, int len, long inv,
+                             int[] product) throws Throwable {
+        int[] result =
+            (a == b) ? (int[]) montgomerySquareHandle.invokeExact(a, n, len, inv, product)
+                     : (int[]) montgomeryMultiplyHandle.invokeExact(a, b, n, len, inv, product);
+        return Arrays.copyOf(result, len);
+    }
+
+    // Invoke the private constructor BigInteger(int[]).
+    BigInteger newBigInteger(int[] val) throws Throwable {
+        return (BigInteger) bigIntegerConstructorHandle.invokeExact(1, val);
+    }
+
+    // Get the private field BigInteger.mag
+    int[] mag(BigInteger n) {
+        try {
+            return (int[]) bigIntegerMagField.get(n);
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    // Montgomery multiplication
+    // Calculate a * b * r^-1 mod n)
+    //
+    // R is a power of the word size
+    // N' = R^-1 mod N
+    //
+    // T := ab
+    // m := (T mod R)N' mod R [so 0 <= m < R]
+    // t := (T + mN)/R
+    // if t >= N then return t - N else return t
+    //
+    BigInteger montgomeryMultiply(BigInteger a, BigInteger b, BigInteger N,
+            int len, BigInteger n_prime)
+            throws Throwable {
+        BigInteger T = a.multiply(b);
+        BigInteger R = BigInteger.ONE.shiftLeft(len*32);
+        BigInteger mask = R.subtract(BigInteger.ONE);
+        BigInteger m = (T.and(mask)).multiply(n_prime);
+        m = m.and(mask); // i.e. m.mod(R)
+        T = T.add(m.multiply(N));
+        T = T.shiftRight(len*32); // i.e. T.divide(R)
+        if (T.compareTo(N) > 0) {
+            T = T.subtract(N);
+        }
+        return T;
+    }
+
+    // Call the Montgomery multiply intrinsic.
+    BigInteger montgomeryMultiply(int[] a_words, int[] b_words, int[] n_words,
+            int len, BigInteger inv)
+            throws Throwable {
+        BigInteger t = montgomeryMultiply(
+                newBigInteger(a_words),
+                newBigInteger(b_words),
+                newBigInteger(n_words),
+                len, inv);
+        return t;
+    }
+
+    // Check that the Montgomery multiply intrinsic returns the same
+    // result as the longhand calculation.
+    void check(int[] a_words, int[] b_words, int[] n_words, int len, BigInteger inv)
+            throws Throwable {
+        BigInteger n = newBigInteger(n_words);
+        BigInteger slow = montgomeryMultiply(a_words, b_words, n_words, len, inv);
+        BigInteger fast
+            = newBigInteger(montgomeryMultiply
+                            (a_words, b_words, n_words, len, inv.longValue(), null));
+        // The intrinsic may not return the same value as the longhand
+        // calculation but they must have the same residue mod N.
+        if (!slow.mod(n).equals(fast.mod(n))) {
+            throw new RuntimeException();
+        }
+    }
+
+    Random rnd = new Random(0);
+
+    // Return a random value of length <= bits in an array of even length
+    int[] random_val(int bits) {
+        int len = (bits+63)/64;  // i.e. length in longs
+        int[] val = new int[len*2];
+        for (int i = 0; i < val.length; i++)
+            val[i] = rnd.nextInt();
+        int leadingZeros = 64 - (bits & 64);
+        if (leadingZeros >= 32) {
+            val[0] = 0;
+            val[1] &= ~(-1l << (leadingZeros & 31));
+        } else {
+            val[0] &= ~(-1l << leadingZeros);
+        }
+        return val;
+    }
+
+    void testOneLength(int lenInBits, int lenInInts) throws Throwable {
+        BigInteger mod = new BigInteger(lenInBits, 2, rnd);
+        BigInteger r = BigInteger.ONE.shiftLeft(lenInInts * 32);
+        BigInteger n_prime = mod.modInverse(r).negate();
+
+        // Make n.length even, padding with a zero if necessary
+        int[] n = mag(mod);
+        if (n.length < lenInInts) {
+            int[] x = new int[lenInInts];
+            System.arraycopy(n, 0, x, lenInInts-n.length, n.length);
+            n = x;
+        }
+
+        for (int i = 0; i < 10000; i++) {
+            // multiply
+            check(random_val(lenInBits), random_val(lenInBits), n, lenInInts, n_prime);
+            // square
+            int[] tmp = random_val(lenInBits);
+            check(tmp, tmp, n, lenInInts, n_prime);
+        }
+    }
+
+    // Test the Montgomery multiply intrinsic with a bunch of random
+    // values of varying lengths.  Do this for long enough that the
+    // caller of the intrinsic is C2-compiled.
+    void testResultValues() throws Throwable {
+        // Test a couple of interesting edge cases.
+        testOneLength(1024, 32);
+        testOneLength(1025, 34);
+        for (int j = 10; j > 0; j--) {
+            // Construct a random prime whose length in words is even
+            int lenInBits = rnd.nextInt(2048) + 64;
+            int lenInInts = (lenInBits + 63)/64*2;
+            testOneLength(lenInBits, lenInInts);
+        }
+    }
+
+    // Range checks
+    void testOneMontgomeryMultiplyCheck(int[] a, int[] b, int[] n, int len, long inv,
+                                        int[] product, Class klass) {
+        try {
+            montgomeryMultiply(a, b, n, len, inv, product);
+        } catch (Throwable ex) {
+            if (klass.isAssignableFrom(ex.getClass()))
+                return;
+            throw new RuntimeException(klass + " expected, " + ex + " was thrown");
+        }
+        throw new RuntimeException(klass + " expected, was not thrown");
+    }
+
+    void testOneMontgomeryMultiplyCheck(int[] a, int[] b, BigInteger n, int len, BigInteger inv,
+            Class klass) {
+        testOneMontgomeryMultiplyCheck(a, b, mag(n), len, inv.longValue(), null, klass);
+    }
+
+    void testOneMontgomeryMultiplyCheck(int[] a, int[] b, BigInteger n, int len, BigInteger inv,
+            int[] product, Class klass) {
+        testOneMontgomeryMultiplyCheck(a, b, mag(n), len, inv.longValue(), product, klass);
+    }
+
+    void testMontgomeryMultiplyChecks() {
+        int[] blah = random_val(40);
+        int[] small = random_val(39);
+        BigInteger mod = new BigInteger(40*32 , 2, rnd);
+        BigInteger r = BigInteger.ONE.shiftLeft(40*32);
+        BigInteger n_prime = mod.modInverse(r).negate();
+
+        // Length out of range: square
+        testOneMontgomeryMultiplyCheck(blah, blah, mod, 41, n_prime, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(blah, blah, mod, 0, n_prime, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(blah, blah, mod, -1, n_prime, IllegalArgumentException.class);
+        // As above, but for multiply
+        testOneMontgomeryMultiplyCheck(blah, blah.clone(), mod, 41, n_prime, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(blah, blah.clone(), mod, 0, n_prime, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(blah, blah.clone(), mod, 0, n_prime, IllegalArgumentException.class);
+
+        // Length odd
+        testOneMontgomeryMultiplyCheck(small, small, mod, 39, n_prime, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(small, small, mod, 0, n_prime, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(small, small, mod, -1, n_prime, IllegalArgumentException.class);
+        // As above, but for multiply
+        testOneMontgomeryMultiplyCheck(small, small.clone(), mod, 39, n_prime, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(small, small.clone(), mod, 0, n_prime, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(small, small.clone(), mod, -1, n_prime, IllegalArgumentException.class);
+
+        // array too small
+        testOneMontgomeryMultiplyCheck(blah, blah, mod, 40, n_prime, small, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(blah, blah.clone(), mod, 40, n_prime, small, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(small, blah, mod, 40, n_prime, blah, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(blah, small, mod, 40, n_prime, blah, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(blah, blah, mod, 40, n_prime, small, IllegalArgumentException.class);
+        testOneMontgomeryMultiplyCheck(small, small, mod, 40, n_prime, blah, IllegalArgumentException.class);
+    }
+
+    public static void main(String args[]) {
+        try {
+            new MontgomeryMultiplyTest().testMontgomeryMultiplyChecks();
+            new MontgomeryMultiplyTest().testResultValues();
+        } catch (Throwable ex) {
+            throw new RuntimeException(ex);
+        }
+     }
+}
diff --git a/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java b/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java
new file mode 100644
index 0000000..1c58908
--- /dev/null
+++ b/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8081778
+ * @summary Add C2 x86 intrinsic for BigInteger::mulAdd() method
+ *
+ * @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch
+ *      -XX:+IgnoreUnrecognizedVMOptions -XX:-UseSquareToLenIntrinsic -XX:-UseMultiplyToLenIntrinsic
+ *      -XX:+UseMulAddIntrinsic
+ *      -XX:CompileCommand=dontinline,TestMulAdd::main
+ *      -XX:CompileCommand=option,TestMulAdd::base_multiply,ccstr,DisableIntrinsic,_mulAdd
+ *      -XX:CompileCommand=option,java.math.BigInteger::multiply,ccstr,DisableIntrinsic,_mulAdd
+ *      -XX:CompileCommand=option,java.math.BigInteger::square,ccstr,DisableIntrinsic,_mulAdd
+ *      -XX:CompileCommand=option,java.math.BigInteger::squareToLen,ccstr,DisableIntrinsic,_mulAdd
+ *      -XX:CompileCommand=option,java.math.BigInteger::mulAdd,ccstr,DisableIntrinsic,_mulAdd
+ *      -XX:CompileCommand=inline,java.math.BigInteger::multiply
+ *      -XX:CompileCommand=inline,java.math.BigInteger::square
+ *      -XX:CompileCommand=inline,java.math.BigInteger::squareToLen
+ *      -XX:CompileCommand=inline,java.math.BigInteger::mulAdd TestMulAdd
+ */
+
+import java.util.Random;
+import java.math.*;
+
+public class TestMulAdd {
+
+    // Avoid intrinsic by preventing inlining multiply() and mulAdd().
+    public static BigInteger base_multiply(BigInteger op1) {
+      return op1.multiply(op1);
+    }
+
+    // Generate mulAdd() intrinsic by inlining multiply().
+    public static BigInteger new_multiply(BigInteger op1) {
+      return op1.multiply(op1);
+    }
+
+    public static boolean bytecompare(BigInteger b1, BigInteger b2) {
+      byte[] data1 = b1.toByteArray();
+      byte[] data2 = b2.toByteArray();
+      if (data1.length != data2.length)
+        return false;
+      for (int i = 0; i < data1.length; i++) {
+        if (data1[i] != data2[i])
+          return false;
+      }
+      return true;
+    }
+
+    public static String stringify(BigInteger b) {
+      String strout= "";
+      byte [] data = b.toByteArray();
+      for (int i = 0; i < data.length; i++) {
+        strout += (String.format("%02x",data[i]) + " ");
+      }
+      return strout;
+    }
+
+    public static void main(String args[]) throws Exception {
+
+      BigInteger oldsum = new BigInteger("0");
+      BigInteger newsum = new BigInteger("0");
+
+      BigInteger b1, b2, oldres, newres;
+
+      Random rand = new Random();
+      long seed = System.nanoTime();
+      Random rand1 = new Random();
+      long seed1 = System.nanoTime();
+      rand.setSeed(seed);
+      rand1.setSeed(seed1);
+
+      for (int j = 0; j < 100000; j++) {
+        int rand_int = rand1.nextInt(3136)+32;
+        b1 = new BigInteger(rand_int, rand);
+
+        oldres = base_multiply(b1);
+        newres = new_multiply(b1);
+
+        oldsum = oldsum.add(oldres);
+        newsum = newsum.add(newres);
+
+        if (!bytecompare(oldres,newres)) {
+          System.out.print("mismatch for:b1:" + stringify(b1) + " :oldres:" + stringify(oldres) + " :newres:" + stringify(newres));
+          System.out.println(b1);
+          throw new Exception("Failed");
+        }
+      }
+      if (!bytecompare(oldsum,newsum))  {
+        System.out.println("Failure: oldsum:" + stringify(oldsum) + " newsum:" + stringify(newsum));
+        throw new Exception("Failed");
+      } else {
+        System.out.println("Success");
+      }
+   }
+}
diff --git a/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java b/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java
new file mode 100644
index 0000000..47c1e47
--- /dev/null
+++ b/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8081778
+ * @summary Add C2 x86 intrinsic for BigInteger::squareToLen() method
+ *
+ * @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch
+ *      -XX:+IgnoreUnrecognizedVMOptions
+ *      -XX:+UseSquareToLenIntrinsic
+ *      -XX:CompileCommand=exclude,TestSquareToLen::main
+ *      -XX:CompileCommand=option,TestSquareToLen::base_multiply,ccstr,DisableIntrinsic,_squareToLen
+ *      -XX:CompileCommand=option,java.math.BigInteger::multiply,ccstr,DisableIntrinsic,_squareToLen
+ *      -XX:CompileCommand=option,java.math.BigInteger::square,ccstr,DisableIntrinsic,_squareToLen
+ *      -XX:CompileCommand=option,java.math.BigInteger::squareToLen,ccstr,DisableIntrinsic,_squareToLen
+ *      -XX:CompileCommand=inline,java.math.BigInteger::multiply
+ *      -XX:CompileCommand=inline,java.math.BigInteger::square
+ *      -XX:CompileCommand=inline,java.math.BigInteger::squareToLen TestSquareToLen
+ */
+
+import java.util.Random;
+import java.math.*;
+
+public class TestSquareToLen {
+
+    // Avoid intrinsic by preventing inlining multiply() and squareToLen().
+    public static BigInteger base_multiply(BigInteger op1) {
+      return op1.multiply(op1);
+    }
+
+    // Generate squareToLen() intrinsic by inlining multiply().
+    public static BigInteger new_multiply(BigInteger op1) {
+      return op1.multiply(op1);
+    }
+
+    public static boolean bytecompare(BigInteger b1, BigInteger b2) {
+      byte[] data1 = b1.toByteArray();
+      byte[] data2 = b2.toByteArray();
+      if (data1.length != data2.length)
+        return false;
+      for (int i = 0; i < data1.length; i++) {
+        if (data1[i] != data2[i])
+          return false;
+      }
+      return true;
+    }
+
+    public static String stringify(BigInteger b) {
+      String strout= "";
+      byte [] data = b.toByteArray();
+      for (int i = 0; i < data.length; i++) {
+        strout += (String.format("%02x",data[i]) + " ");
+      }
+      return strout;
+    }
+
+    public static void main(String args[]) throws Exception {
+
+      BigInteger oldsum = new BigInteger("0");
+      BigInteger newsum = new BigInteger("0");
+
+      BigInteger b1, b2, oldres, newres;
+
+      Random rand = new Random();
+      long seed = System.nanoTime();
+      Random rand1 = new Random();
+      long seed1 = System.nanoTime();
+      rand.setSeed(seed);
+      rand1.setSeed(seed1);
+
+      for (int j = 0; j < 100000; j++) {
+        int rand_int = rand1.nextInt(3136)+32;
+        b1 = new BigInteger(rand_int, rand);
+
+        oldres = base_multiply(b1);
+        newres = new_multiply(b1);
+
+        oldsum = oldsum.add(oldres);
+        newsum = newsum.add(newres);
+
+        if (!bytecompare(oldres,newres)) {
+          System.out.print("mismatch for:b1:" + stringify(b1) + " :oldres:" + stringify(oldres) + " :newres:" + stringify(newres));
+          System.out.println(b1);
+          throw new Exception("Failed");
+        }
+      }
+      if (!bytecompare(oldsum,newsum))  {
+        System.out.println("Failure: oldsum:" + stringify(oldsum) + " newsum:" + stringify(newsum));
+        throw new Exception("Failed");
+      } else {
+        System.out.println("Success");
+      }
+   }
+}
diff --git a/hotspot/test/compiler/loopopts/TestLoopPeeling.java b/hotspot/test/compiler/loopopts/TestLoopPeeling.java
new file mode 100644
index 0000000..d2d2e3d
--- /dev/null
+++ b/hotspot/test/compiler/loopopts/TestLoopPeeling.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8078262
+ * @summary Tests correct dominator information after loop peeling.
+ * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestLoopPeeling::test* TestLoopPeeling
+ */
+public class TestLoopPeeling {
+
+    public int[] array = new int[100];
+
+    public static void main(String args[]) {
+        TestLoopPeeling test = new TestLoopPeeling();
+        try {
+            test.testArrayAccess(0, 1);
+            test.testArrayAllocation(0, 1);
+        } catch (Exception e) {
+            // Ignore exceptions
+        }
+    }
+
+    public void testArrayAccess(int index, int inc) {
+        int storeIndex = -1;
+
+        for (; index < 10; index += inc) {
+            // This loop invariant check triggers loop peeling because it can
+            // be moved out of the loop (see 'IdealLoopTree::policy_peeling').
+            if (inc == 42) return;
+
+            // This loop variant usage of LShiftL( ConvI2L( Phi(storeIndex) ) )
+            // prevents the split if optimization that would otherwise clone the
+            // LShiftL and ConvI2L nodes and assign them to their corresponding array
+            // address computation (see 'PhaseIdealLoop::split_if_with_blocks_post').
+            if (storeIndex > 0 && array[storeIndex] == 42) return;
+
+            if (index == 42) {
+                // This store and the corresponding range check are moved out of the
+                // loop and both used after old loop and the peeled iteration exit.
+                // For the peeled iteration, storeIndex is always -1 and the ConvI2L
+                // is replaced by TOP. However, the range check is not folded because
+                // we don't do the split if optimization in PhaseIdealLoop2.
+                // As a result, we have a (dead) control path from the peeled iteration
+                // to the StoreI but the data path is removed.
+                array[storeIndex] = 1;
+                return;
+            }
+
+            storeIndex++;
+        }
+    }
+
+    public byte[] testArrayAllocation(int index, int inc) {
+        int allocationCount = -1;
+        byte[] result;
+
+        for (; index < 10; index += inc) {
+            // This loop invariant check triggers loop peeling because it can
+            // be moved out of the loop (see 'IdealLoopTree::policy_peeling').
+            if (inc == 42) return null;
+
+            if (index == 42) {
+                // This allocation and the corresponding size check are moved out of the
+                // loop and both used after old loop and the peeled iteration exit.
+                // For the peeled iteration, allocationCount is always -1 and the ConvI2L
+                // is replaced by TOP. However, the size check is not folded because
+                // we don't do the split if optimization in PhaseIdealLoop2.
+                // As a result, we have a (dead) control path from the peeled iteration
+                // to the allocation but the data path is removed.
+                result = new byte[allocationCount];
+                return result;
+            }
+
+            allocationCount++;
+        }
+        return null;
+    }
+}
+
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index 046ae7b..4d8bb66 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -544,6 +544,19 @@
 aa9485a887b7e983f9743c9c114de2055055300d jdk8u74-b01
 b3325c0526621f9ddf82738373cc8f8947dab195 jdk8u74-b02
 2b3d0e6f3cd179e2346679af2a8881bb6b20f968 jdk8u72-b31
+aeecbaa27f807ce0656a108cd0e81669724b8d1b jdk8u73-b00
+9009a8b2b55256764dd304902b04a3dea2597684 jdk8u73-b01
+7a021985ef009c3a88a206d6f295f17e382f98b9 jdk8u73-b02
+2e7b89c7f79794b872e73708fdaa3ed9331ec45d jdk8u74-b00
+aa9485a887b7e983f9743c9c114de2055055300d jdk8u74-b01
+b3325c0526621f9ddf82738373cc8f8947dab195 jdk8u74-b02
+c583ac51e2c78d6c59786b447986baf7b961518d jdk8u74-b31
+4c8fd0814bf0bcbc9666a29e1daa35c64c7bb57a jdk8u74-b32
+8cc52edbb741c42e09f4b132ca0a759d3de6f848 jdk8u77-b00
+8f0ed89698a28138065b6b941769650627636745 jdk8u77-b01
+27f1130320a55b6b89024cb8baa93c8767c516d2 jdk8u77-b02
+1c71899e85662239085fab94ad5c26441e7a80cd jdk8u77-b03
+a49d8c7db1e5b3ab84561069bd4ae63579139878 jdk8u77-b31
 eca165c0654ac2e1926b50655e5ed5e9b73ca674 jdk8u75-b00
 06cdf5dc679e0fef7c8e37c5c712b2c5891c1444 jdk8u75-b01
 26c297e9f11b78b55cdefd22849ae4fe55042a5b jdk8u75-b02
@@ -556,6 +569,13 @@
 1b3ef7edccbcee10699c647da23b98cfe7ec1ed7 jdk8u75-b09
 e926cbc930ff727229191242a145ac625ddd7fa0 jdk8u75-b10
 ce9b845453027a7a6309398b1ca2f32cf1534ae5 jdk8u75-b12
+8cc52edbb741c42e09f4b132ca0a759d3de6f848 jdk8u77-b00
+8f0ed89698a28138065b6b941769650627636745 jdk8u77-b01
+27f1130320a55b6b89024cb8baa93c8767c516d2 jdk8u77-b02
+1c71899e85662239085fab94ad5c26441e7a80cd jdk8u77-b03
+6b0d1f04c4808aaab32771e0892ac83e66714ecb jdk8u91-b00
+817898d53814da42f567995c921f3ea90016dccc jdk8u91-b13
+f6bda5729ff86e9691cd51f04261c3942974cecc jdk8u91-b14
 acbcb6682c9b3e66f9cc61a6a62e8cb5f24c75d3 jdk8u76-b00
 b3c914ad842d61818e0c5850409f77478b13acc6 jdk8u76-b01
 7711933ec18462ece8a1b9a9527ec873c520b1ab jdk8u76-b02
@@ -568,3 +588,7 @@
 2e5841f57df44b0f49e49ef3b827a7babf51bca7 jdk8u76-b09
 8c4b258892025ee4d5df4109f974ba4665ee1208 jdk8u76-b10
 6afc87bdaa7b93855e152aad437305ce0a42251a jdk8u76-b11
+233768376a3649b3f1f4653fe1c433271fc776ee jdk8u76-b12
+7e43e115dfafee70152a01b99aa9de25b4410570 jdk8u92-b00
+1bce84411d37ecf9a4335d1348f4b2f0b7ab6e08 jdk8u92-b13
+fb9f98ed6ef2505a424864f0a9468e59298fede6 jdk8u92-b14
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 7244326..f74c74b 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -531,12 +531,20 @@
 4c28352ce19bc25be5de681868a8cddb3f3644a8 jdk8u72-b13
 1a523f4b8cc77ef9dfb6d8191742dcd616cd9093 jdk8u72-b14
 2f840ac0adf079f0d2f0bac7a9c3fae6ea651271 jdk8u72-b15
+744fab401c4b326f142f5110ad523b1b22f973c8 jdk8u72-b31
 8da626c14c138dd41d4c685800351bf675048628 jdk8u73-b00
 dfc9feacece48fa8450b997e463afae2c1539ac3 jdk8u73-b01
 06fb882f8ed7ff3e58f7aa57e526e55c25ae9992 jdk8u73-b02
 4a5f76111c0b056357d4bdd3e015d649de2db591 jdk8u74-b00
 621e4ac137cd4a04ac1279e75d7fd0625765fd03 jdk8u74-b01
 6cfef18571fd35f45bada34cf4da4b1492ddb878 jdk8u74-b02
+e2d83c243af551722c88fe2dd391364373e2bd3a jdk8u74-b31
+62291bde8b5ea2288c0729982681baec7cd0451f jdk8u74-b32
+a2f8a45d70b21e450fac7ae7d5ca71ce853cf3d0 jdk8u77-b00
+dd34713088c23b7c6ef1adc071dd635bc7bda744 jdk8u77-b01
+7c319d6e0d4c59ebde91b88ba1391ace165b2f01 jdk8u77-b02
+c6f67bea4466783433b1bf1f83a4eb6784a5eb55 jdk8u77-b03
+bedbb9b6cf59d5da68478a4b49bb2fdfc43a4f2c jdk8u77-b31
 744fab401c4b326f142f5110ad523b1b22f973c8 jdk8u72-b31
 7d7b3488f44e77bedbbcbdee5a4415e5a5bd930c jdk8u75-b00
 d0161a6ecd3bf8c9953e979db8318177e4f2aa86 jdk8u75-b01
@@ -550,6 +558,13 @@
 c302ec60295cd1a5b57e43c28e387556980d1350 jdk8u75-b09
 945844568e956b9b68003f2b0f0528521b578d98 jdk8u75-b10
 ee0c5d0875a3c6022fde6855c6353b68f746f6cd jdk8u75-b12
+a2f8a45d70b21e450fac7ae7d5ca71ce853cf3d0 jdk8u77-b00
+dd34713088c23b7c6ef1adc071dd635bc7bda744 jdk8u77-b01
+7c319d6e0d4c59ebde91b88ba1391ace165b2f01 jdk8u77-b02
+c6f67bea4466783433b1bf1f83a4eb6784a5eb55 jdk8u77-b03
+f66ee2329cd21c3485de1b8e0588f55882a56e0d jdk8u91-b00
+be5935ee38f1bc5132cf318f7badb61af86e2396 jdk8u91-b13
+e71f424e2c966a495b1d47693317288f291a794a jdk8u91-b14
 6aba0f814a15966e47aeab61b466894b82c03c70 jdk8u76-b00
 60789eebd1fe440255fd3f504221dc8b5553b8c2 jdk8u76-b01
 8c7d476c446940edd913ba5a3ca36975febdac28 jdk8u76-b02
@@ -562,3 +577,7 @@
 c50275b7bb7aa23ab6c83423f3b1d8e02f604854 jdk8u76-b09
 9a7ea7a7ab734047e6bae7c354f503e7b71bf4c2 jdk8u76-b10
 f31ede81ad1e14724b49c71bae8183e8e36986d0 jdk8u76-b11
+fad3981b329a0d309f4922bbca7335973e32e50f jdk8u76-b12
+451d700ba30ee0d3d201090a9d5dd606b988820e jdk8u92-b00
+008547c7dd3e324c46c2711b54285ca99e2ae0b9 jdk8u92-b13
+759ba92444a9e85434cb381f437aba65e3c9f780 jdk8u92-b14
diff --git a/jdk/.hgtags b/jdk/.hgtags
index bf7c770..74e17a5 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -534,12 +534,15 @@
 d841d3fdae44f120883dab0a3a809a054cd0274b jdk8u72-b13
 f6d24d424cd2af4d2612f7737d3d9a25f58b882d jdk8u72-b14
 f3e86cc607260bae368b52d88d7bc8883ee767e3 jdk8u72-b15
+1d4b343084874b1afa1cdd504b9b1e50bab7f121 jdk8u72-b31
 892eb9ab179650b89b7bab6bc42f079391c98624 jdk8u73-b00
 9b77d3ca0d66a117c3cc0e0a74b8059545b22f0e jdk8u73-b01
 2ab13901d6f14bab0dcf4823d5e378a421fba7e2 jdk8u73-b02
 9a843dc6f959f62c61014a3a71ec9aa329f1daf1 jdk8u74-b00
 e829ab80dfd828803aa8837411900faeaa1254a5 jdk8u74-b01
 32c49f4a16599e376e4e46bb33c7bcc486e52ff3 jdk8u74-b02
+9c828e688240362b6f1b761b619cdaa070462c4e jdk8u74-b31
+6968ca30f8fdc9429fcd56187e16f46b215b474b jdk8u74-b32
 1d4b343084874b1afa1cdd504b9b1e50bab7f121 jdk8u72-b31
 7cfd2c51c501df909833aa0fb6e40c50c61621ed jdk8u75-b00
 9e00a43602f87930c2318b2567002871ad9c59dd jdk8u75-b01
@@ -553,6 +556,14 @@
 e6f4eb91a1fa895c2f4520e4cca0ae6f2ca14fbb jdk8u75-b09
 93ea7fd6a5a26940d5a2b020c4e9012a85685a5a jdk8u75-b10
 748ca164767d268e1739748f4df02b623397446c jdk8u75-b12
+02e1209648050922a5a9f2789d9d359795f6f834 jdk8u77-b00
+f08584a0fde9344b0aa4766984266ca68b9a5018 jdk8u77-b01
+1a3e81c05703bb36def80a57681e1692c866f621 jdk8u77-b02
+c44179bce874a97e93ffd7b76a226af417e017a4 jdk8u77-b03
+8c3f4e540348daed7263bae092b0e5f212478b00 jdk8u77-b31
+71f59a00df6c8f3bd5c6d6631a4988a431adab56 jdk8u91-b00
+7ade7a1ab10ff893f62cce9440b4a839aa19c250 jdk8u91-b13
+f8725698a870b6be82fad578e78a55910b259975 jdk8u91-b14
 39baa472e20c13c0eb1243eb5dce589e82f78143 jdk8u76-b00
 6ea3aea950d19d803475b3f4d704a2942e71b302 jdk8u76-b01
 4de4cffb5988cd68959ce4bbd14c6d4547078c91 jdk8u76-b02
@@ -565,3 +576,7 @@
 cbafa4c725f9d80fd369dd7979dd97682ae284e6 jdk8u76-b09
 8274df0f06623726ff62324671a4ea24a4c3bfc5 jdk8u76-b10
 17f5065e3873fe409bff8c026fa5fe6349b08157 jdk8u76-b11
+0ca25fdd520a0a74f0a488de263641d9f76b8664 jdk8u76-b12
+ea965fea71f612d65013192aa637d88e05915b10 jdk8u92-b00
+cc8d0d6c6f9543120836e70e0aa3fa9c9b6fe0f3 jdk8u92-b13
+4f06a20cdc59ce9742e6538ff4b9040baba0778a jdk8u92-b14
diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java
index 9bf5736..842af56 100644
--- a/jdk/src/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java
@@ -653,6 +653,9 @@
         if (!checkName(name))
             throw new NoClassDefFoundError("IllegalName: " + name);
 
+        // Note:  Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
+        // relies on the fact that spoofing is impossible if a class has a name
+        // of the form "java.*"
         if ((name != null) && name.startsWith("java.")) {
             throw new SecurityException
                 ("Prohibited package name: " +
diff --git a/jdk/src/share/classes/java/lang/invoke/MemberName.java b/jdk/src/share/classes/java/lang/invoke/MemberName.java
index d0c6e42..bcc08e7 100644
--- a/jdk/src/share/classes/java/lang/invoke/MemberName.java
+++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java
@@ -783,7 +783,7 @@
         assert(isResolved() == isResolved);
     }
 
-    void checkForTypeAlias() {
+    void checkForTypeAlias(Class<?> refc) {
         if (isInvocable()) {
             MethodType type;
             if (this.type instanceof MethodType)
@@ -791,16 +791,16 @@
             else
                 this.type = type = getMethodType();
             if (type.erase() == type)  return;
-            if (VerifyAccess.isTypeVisible(type, clazz))  return;
-            throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
+            if (VerifyAccess.isTypeVisible(type, refc))  return;
+            throw new LinkageError("bad method type alias: "+type+" not visible from "+refc);
         } else {
             Class<?> type;
             if (this.type instanceof Class<?>)
                 type = (Class<?>) this.type;
             else
                 this.type = type = getFieldType();
-            if (VerifyAccess.isTypeVisible(type, clazz))  return;
-            throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
+            if (VerifyAccess.isTypeVisible(type, refc))  return;
+            throw new LinkageError("bad field type alias: "+type+" not visible from "+refc);
         }
     }
 
@@ -959,10 +959,25 @@
             MemberName m = ref.clone();  // JVM will side-effect the ref
             assert(refKind == m.getReferenceKind());
             try {
+                // There are 4 entities in play here:
+                //   * LC: lookupClass
+                //   * REFC: symbolic reference class (MN.clazz before resolution);
+                //   * DEFC: resolved method holder (MN.clazz after resolution);
+                //   * PTYPES: parameter types (MN.type)
+                //
+                // What we care about when resolving a MemberName is consistency between DEFC and PTYPES.
+                // We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM
+                // finishes the resolution, so do TA checks right after MHN.resolve() is over.
+                //
+                // All parameters passed by a caller are checked against MH type (PTYPES) on every invocation,
+                // so it is safe to call a MH from any context.
+                //
+                // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
+                // participate in method selection.
                 m = MethodHandleNatives.resolve(m, lookupClass);
-                m.checkForTypeAlias();
+                m.checkForTypeAlias(m.getDeclaringClass());
                 m.resolution = null;
-            } catch (LinkageError ex) {
+            } catch (ClassNotFoundException | LinkageError ex) {
                 // JVM reports that the "bytecode behavior" would get an error
                 assert(!m.isResolved());
                 m.resolution = ex;
diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java
index 0f5169e..ecc1460 100644
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java
@@ -45,7 +45,7 @@
 
     static native void init(MemberName self, Object ref);
     static native void expand(MemberName self);
-    static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError;
+    static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError, ClassNotFoundException;
     static native int getMembers(Class<?> defc, String matchName, String matchSig,
             int matchFlags, Class<?> caller, int skip, MemberName[] results);
 
diff --git a/jdk/src/share/classes/java/math/BigInteger.java b/jdk/src/share/classes/java/math/BigInteger.java
index 6fa5d42..e35c723 100644
--- a/jdk/src/share/classes/java/math/BigInteger.java
+++ b/jdk/src/share/classes/java/math/BigInteger.java
@@ -276,6 +276,15 @@
      */
     private static final int MULTIPLY_SQUARE_THRESHOLD = 20;
 
+    /**
+     * The threshold for using an intrinsic version of
+     * implMontgomeryXXX to perform Montgomery multiplication.  If the
+     * number of ints in the number is more than this value we do not
+     * use the intrinsic.
+     */
+    private static final int MONTGOMERY_INTRINSIC_THRESHOLD = 512;
+
+
     // Constructors
 
     /**
@@ -1573,7 +1582,7 @@
      * Multiplies int arrays x and y to the specified lengths and places
      * the result into z. There will be no leading zeros in the resultant array.
      */
-    private int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) {
+    private static int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) {
         int xstart = xlen - 1;
         int ystart = ylen - 1;
 
@@ -1897,6 +1906,43 @@
      * int array z.  The contents of x are not changed.
      */
     private static final int[] squareToLen(int[] x, int len, int[] z) {
+         int zlen = len << 1;
+         if (z == null || z.length < zlen)
+             z = new int[zlen];
+
+         // Execute checks before calling intrinsified method.
+         implSquareToLenChecks(x, len, z, zlen);
+         return implSquareToLen(x, len, z, zlen);
+     }
+
+     /**
+      * Parameters validation.
+      */
+     private static void implSquareToLenChecks(int[] x, int len, int[] z, int zlen) throws RuntimeException {
+         if (len < 1) {
+             throw new IllegalArgumentException("invalid input length: " + len);
+         }
+         if (len > x.length) {
+             throw new IllegalArgumentException("input length out of bound: " +
+                                        len + " > " + x.length);
+         }
+         if (len * 2 > z.length) {
+             throw new IllegalArgumentException("input length out of bound: " +
+                                        (len * 2) + " > " + z.length);
+         }
+         if (zlen < 1) {
+             throw new IllegalArgumentException("invalid input length: " + zlen);
+         }
+         if (zlen > z.length) {
+             throw new IllegalArgumentException("input length out of bound: " +
+                                        len + " > " + z.length);
+         }
+     }
+
+     /**
+      * Java Runtime may use intrinsic for this method.
+      */
+     private static final int[] implSquareToLen(int[] x, int len, int[] z, int zlen) {
         /*
          * The algorithm used here is adapted from Colin Plumb's C library.
          * Technique: Consider the partial products in the multiplication
@@ -1931,9 +1977,6 @@
          * again.  The low bit is simply a copy of the low bit of the
          * input, so it doesn't need special care.
          */
-        int zlen = len << 1;
-        if (z == null || z.length < zlen)
-            z = new int[zlen];
 
         // Store the squares, right shifted one bit (i.e., divided by 2)
         int lastProductLowWord = 0;
@@ -2501,6 +2544,75 @@
         return (invertResult ? result.modInverse(m) : result);
     }
 
+    // Montgomery multiplication.  These are wrappers for
+    // implMontgomeryXX routines which are expected to be replaced by
+    // virtual machine intrinsics.  We don't use the intrinsics for
+    // very large operands: MONTGOMERY_INTRINSIC_THRESHOLD should be
+    // larger than any reasonable crypto key.
+    private static int[] montgomeryMultiply(int[] a, int[] b, int[] n, int len, long inv,
+                                            int[] product) {
+        implMontgomeryMultiplyChecks(a, b, n, len, product);
+        if (len > MONTGOMERY_INTRINSIC_THRESHOLD) {
+            // Very long argument: do not use an intrinsic
+            product = multiplyToLen(a, len, b, len, product);
+            return montReduce(product, n, len, (int)inv);
+        } else {
+            return implMontgomeryMultiply(a, b, n, len, inv, materialize(product, len));
+        }
+    }
+    private static int[] montgomerySquare(int[] a, int[] n, int len, long inv,
+                                          int[] product) {
+        implMontgomeryMultiplyChecks(a, a, n, len, product);
+        if (len > MONTGOMERY_INTRINSIC_THRESHOLD) {
+            // Very long argument: do not use an intrinsic
+            product = squareToLen(a, len, product);
+            return montReduce(product, n, len, (int)inv);
+        } else {
+            return implMontgomerySquare(a, n, len, inv, materialize(product, len));
+        }
+    }
+
+    // Range-check everything.
+    private static void implMontgomeryMultiplyChecks
+        (int[] a, int[] b, int[] n, int len, int[] product) throws RuntimeException {
+        if (len % 2 != 0) {
+            throw new IllegalArgumentException("input array length must be even: " + len);
+        }
+
+        if (len < 1) {
+            throw new IllegalArgumentException("invalid input length: " + len);
+        }
+
+        if (len > a.length ||
+            len > b.length ||
+            len > n.length ||
+            (product != null && len > product.length)) {
+            throw new IllegalArgumentException("input array length out of bound: " + len);
+        }
+    }
+
+    // Make sure that the int array z (which is expected to contain
+    // the result of a Montgomery multiplication) is present and
+    // sufficiently large.
+    private static int[] materialize(int[] z, int len) {
+         if (z == null || z.length < len)
+             z = new int[len];
+         return z;
+    }
+
+    // These methods are intended to be be replaced by virtual machine
+    // intrinsics.
+    private static int[] implMontgomeryMultiply(int[] a, int[] b, int[] n, int len,
+                                         long inv, int[] product) {
+        product = multiplyToLen(a, len, b, len, product);
+        return montReduce(product, n, len, (int)inv);
+    }
+    private static int[] implMontgomerySquare(int[] a, int[] n, int len,
+                                       long inv, int[] product) {
+        product = squareToLen(a, len, product);
+        return montReduce(product, n, len, (int)inv);
+    }
+
     static int[] bnExpModThreshTable = {7, 25, 81, 241, 673, 1793,
                                                 Integer.MAX_VALUE}; // Sentinel
 
@@ -2579,6 +2691,17 @@
         int[] mod = z.mag;
         int modLen = mod.length;
 
+        // Make modLen even. It is conventional to use a cryptographic
+        // modulus that is 512, 768, 1024, or 2048 bits, so this code
+        // will not normally be executed. However, it is necessary for
+        // the correct functioning of the HotSpot intrinsics.
+        if ((modLen & 1) != 0) {
+            int[] x = new int[modLen + 1];
+            System.arraycopy(mod, 0, x, 1, modLen);
+            mod = x;
+            modLen++;
+        }
+
         // Select an appropriate window size
         int wbits = 0;
         int ebits = bitLength(exp, exp.length);
@@ -2597,8 +2720,10 @@
         for (int i=0; i < tblmask; i++)
             table[i] = new int[modLen];
 
-        // Compute the modular inverse
-        int inv = -MutableBigInteger.inverseMod32(mod[modLen-1]);
+        // Compute the modular inverse of the least significant 64-bit
+        // digit of the modulus
+        long n0 = (mod[modLen-1] & LONG_MASK) + ((mod[modLen-2] & LONG_MASK) << 32);
+        long inv = -MutableBigInteger.inverseMod64(n0);
 
         // Convert base to Montgomery form
         int[] a = leftShift(base, base.length, modLen << 5);
@@ -2606,6 +2731,8 @@
         MutableBigInteger q = new MutableBigInteger(),
                           a2 = new MutableBigInteger(a),
                           b2 = new MutableBigInteger(mod);
+        b2.normalize(); // MutableBigInteger.divide() assumes that its
+                        // divisor is in normal form.
 
         MutableBigInteger r= a2.divide(b2, q);
         table[0] = r.toIntArray();
@@ -2614,22 +2741,19 @@
         if (table[0].length < modLen) {
            int offset = modLen - table[0].length;
            int[] t2 = new int[modLen];
-           for (int i=0; i < table[0].length; i++)
-               t2[i+offset] = table[0][i];
+           System.arraycopy(table[0], 0, t2, offset, table[0].length);
            table[0] = t2;
         }
 
         // Set b to the square of the base
-        int[] b = squareToLen(table[0], modLen, null);
-        b = montReduce(b, mod, modLen, inv);
+        int[] b = montgomerySquare(table[0], mod, modLen, inv, null);
 
         // Set t to high half of b
         int[] t = Arrays.copyOf(b, modLen);
 
         // Fill in the table with odd powers of the base
         for (int i=1; i < tblmask; i++) {
-            int[] prod = multiplyToLen(t, modLen, table[i-1], modLen, null);
-            table[i] = montReduce(prod, mod, modLen, inv);
+            table[i] = montgomeryMultiply(t, table[i-1], mod, modLen, inv, null);
         }
 
         // Pre load the window that slides over the exponent
@@ -2700,8 +2824,7 @@
                     isone = false;
                 } else {
                     t = b;
-                    a = multiplyToLen(t, modLen, mult, modLen, a);
-                    a = montReduce(a, mod, modLen, inv);
+                    a = montgomeryMultiply(t, mult, mod, modLen, inv, a);
                     t = a; a = b; b = t;
                 }
             }
@@ -2713,8 +2836,7 @@
             // Square the input
             if (!isone) {
                 t = b;
-                a = squareToLen(t, modLen, a);
-                a = montReduce(a, mod, modLen, inv);
+                a = montgomerySquare(t, mod, modLen, inv, a);
                 t = a; a = b; b = t;
             }
         }
@@ -2723,7 +2845,7 @@
         int[] t2 = new int[2*modLen];
         System.arraycopy(b, 0, t2, modLen, modLen);
 
-        b = montReduce(t2, mod, modLen, inv);
+        b = montReduce(t2, mod, modLen, (int)inv);
 
         t2 = Arrays.copyOf(b, modLen);
 
@@ -2791,6 +2913,32 @@
      * Multiply an array by one word k and add to result, return the carry
      */
     static int mulAdd(int[] out, int[] in, int offset, int len, int k) {
+        implMulAddCheck(out, in, offset, len, k);
+        return implMulAdd(out, in, offset, len, k);
+    }
+
+    /**
+     * Parameters validation.
+     */
+    private static void implMulAddCheck(int[] out, int[] in, int offset, int len, int k) {
+        if (len > in.length) {
+            throw new IllegalArgumentException("input length is out of bound: " + len + " > " + in.length);
+        }
+        if (offset < 0) {
+            throw new IllegalArgumentException("input offset is invalid: " + offset);
+        }
+        if (offset > (out.length - 1)) {
+            throw new IllegalArgumentException("input offset is out of bound: " + offset + " > " + (out.length - 1));
+        }
+        if (len > (out.length - offset)) {
+            throw new IllegalArgumentException("input len is out of bound: " + len + " > " + (out.length - offset));
+        }
+    }
+
+    /**
+     * Java Runtime may use intrinsic for this method.
+     */
+    private static int implMulAdd(int[] out, int[] in, int offset, int len, int k) {
         long kLong = k & LONG_MASK;
         long carry = 0;
 
diff --git a/jdk/src/share/classes/java/math/MutableBigInteger.java b/jdk/src/share/classes/java/math/MutableBigInteger.java
index 00e95aa..73a244f 100644
--- a/jdk/src/share/classes/java/math/MutableBigInteger.java
+++ b/jdk/src/share/classes/java/math/MutableBigInteger.java
@@ -2065,6 +2065,21 @@
     }
 
     /**
+     * Returns the multiplicative inverse of val mod 2^64.  Assumes val is odd.
+     */
+    static long inverseMod64(long val) {
+        // Newton's iteration!
+        long t = val;
+        t *= 2 - val*t;
+        t *= 2 - val*t;
+        t *= 2 - val*t;
+        t *= 2 - val*t;
+        t *= 2 - val*t;
+        assert(t * val == 1);
+        return t;
+    }
+
+    /**
      * Calculate the multiplicative inverse of 2^k mod mod, where mod is odd.
      */
     static MutableBigInteger modInverseBP2(MutableBigInteger mod, int k) {
diff --git a/jdk/src/share/classes/javax/swing/TimerQueue.java b/jdk/src/share/classes/javax/swing/TimerQueue.java
index a6791d6..7092b45 100644
--- a/jdk/src/share/classes/javax/swing/TimerQueue.java
+++ b/jdk/src/share/classes/javax/swing/TimerQueue.java
@@ -93,6 +93,9 @@
     void startIfNeeded() {
         if (! running) {
             runningLock.lock();
+            if (running) {
+                return;
+            }
             try {
                 final ThreadGroup threadGroup =
                     AppContext.getAppContext().getThreadGroup();
@@ -168,15 +171,17 @@
         try {
             while (running) {
                 try {
-                    Timer timer = queue.take().getTimer();
+                    DelayedTimer runningTimer = queue.take();
+                    Timer timer = runningTimer.getTimer();
                     timer.getLock().lock();
                     try {
                         DelayedTimer delayedTimer = timer.delayedTimer;
-                        if (delayedTimer != null) {
+                        if (delayedTimer == runningTimer) {
                             /*
-                             * Timer is not removed after we get it from
-                             * the queue and before the lock on the timer is
-                             * acquired
+                             * Timer is not removed (delayedTimer != null)
+                             * or not removed and added (runningTimer == delayedTimer)
+                             * after we get it from the queue and before the
+                             * lock on the timer is acquired
                              */
                             timer.post(); // have timer post an event
                             timer.delayedTimer = null;
diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java
index 190b94b..f134ad1 100644
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -870,18 +870,13 @@
                 int orientation = SwingConstants.VERTICAL;
 
                 // find which scrollbar to scroll, or return if none
-                if (toScroll == null || !toScroll.isVisible()) {
+                if (toScroll == null || !toScroll.isVisible()
+                        || e.isShiftDown()) {
                     toScroll = scrollpane.getHorizontalScrollBar();
                     if (toScroll == null || !toScroll.isVisible()) {
                         return;
                     }
                     orientation = SwingConstants.HORIZONTAL;
-                } else if(e.isShiftDown()){
-                    JScrollBar hScroll = scrollpane.getHorizontalScrollBar();
-                    if (hScroll != null && hScroll.isVisible()) {
-                        toScroll = hScroll;
-                        orientation = SwingConstants.HORIZONTAL;
-                    }
                 }
 
                 e.consume();
diff --git a/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java b/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java
index fc870fc..532fa00 100644
--- a/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java
@@ -185,22 +185,66 @@
      * @param refc the class attempting to make the reference
      */
     public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
-        if (type == refc)  return true;  // easy check
+        if (type == refc) {
+            return true;  // easy check
+        }
         while (type.isArray())  type = type.getComponentType();
-        if (type.isPrimitive() || type == Object.class)  return true;
-        ClassLoader parent = type.getClassLoader();
-        if (parent == null)  return true;
-        ClassLoader child  = refc.getClassLoader();
-        if (child == null)  return false;
-        if (parent == child || loadersAreRelated(parent, child, true))
+        if (type.isPrimitive() || type == Object.class) {
             return true;
-        // Do it the hard way:  Look up the type name from the refc loader.
-        try {
-            Class<?> res = child.loadClass(type.getName());
-            return (type == res);
-        } catch (ClassNotFoundException ex) {
+        }
+        ClassLoader typeLoader = type.getClassLoader();
+        ClassLoader refcLoader = refc.getClassLoader();
+        if (typeLoader == refcLoader) {
+            return true;
+        }
+        if (refcLoader == null && typeLoader != null) {
             return false;
         }
+        if (typeLoader == null && type.getName().startsWith("java.")) {
+            // Note:  The API for actually loading classes, ClassLoader.defineClass,
+            // guarantees that classes with names beginning "java." cannot be aliased,
+            // because class loaders cannot load them directly.
+            return true;
+        }
+
+        // Do it the hard way:  Look up the type name from the refc loader.
+        //
+        // Force the refc loader to report and commit to a particular binding for this type name (type.getName()).
+        //
+        // In principle, this query might force the loader to load some unrelated class,
+        // which would cause this query to fail (and the original caller to give up).
+        // This would be wasted effort, but it is expected to be very rare, occurring
+        // only when an attacker is attempting to create a type alias.
+        // In the normal case, one class loader will simply delegate to the other,
+        // and the same type will be visible through both, with no extra loading.
+        //
+        // It is important to go through Class.forName instead of ClassLoader.loadClass
+        // because Class.forName goes through the JVM system dictionary, which records
+        // the class lookup once for all. This means that even if a not-well-behaved class loader
+        // would "change its mind" about the meaning of the name, the Class.forName request
+        // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
+        // will record the first successful result. Unsuccessful results are not stored.
+        //
+        // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
+        // class loader about the binding of the proposed name (type.getName()).
+        // The looked up type ("res") is compared for equality against the proposed
+        // type ("type") and then is discarded.  Thus, the worst that can happen to
+        // the "child" class loader is that it is bothered to load and report a class
+        // that differs from "type"; this happens once due to JVM system dictionary
+        // memoization.  And the caller never gets to look at the alternate type binding
+        // ("res"), whether it exists or not.
+        final String name = type.getName();
+        Class<?> res = java.security.AccessController.doPrivileged(
+                new java.security.PrivilegedAction<Class>() {
+                    public Class<?> run() {
+                        try {
+                            return Class.forName(name, false, refcLoader);
+                        } catch (ClassNotFoundException | LinkageError e) {
+                            return null; // Assume the class is not found
+                        }
+                    }
+            });
+        return (type == res);
     }
 
     /**
diff --git a/jdk/src/share/classes/sun/security/pkcs/PKCS7.java b/jdk/src/share/classes/sun/security/pkcs/PKCS7.java
index fdc295c..19211ae 100644
--- a/jdk/src/share/classes/sun/security/pkcs/PKCS7.java
+++ b/jdk/src/share/classes/sun/security/pkcs/PKCS7.java
@@ -802,7 +802,8 @@
                                             byte[] content,
                                             String signatureAlgorithm,
                                             URI tsaURI,
-                                            String tSAPolicyID)
+                                            String tSAPolicyID,
+                                            String tSADigestAlg)
         throws CertificateException, IOException, NoSuchAlgorithmException
     {
 
@@ -811,7 +812,8 @@
         if (tsaURI != null) {
             // Timestamp the signature
             HttpTimestamper tsa = new HttpTimestamper(tsaURI);
-            byte[] tsToken = generateTimestampToken(tsa, tSAPolicyID, signature);
+            byte[] tsToken = generateTimestampToken(
+                    tsa, tSAPolicyID, tSADigestAlg, signature);
 
             // Insert the timestamp token into the PKCS #7 signer info element
             // (as an unsigned attribute)
@@ -869,6 +871,7 @@
      */
     private static byte[] generateTimestampToken(Timestamper tsa,
                                                  String tSAPolicyID,
+                                                 String tSADigestAlg,
                                                  byte[] toBeTimestamped)
         throws IOException, CertificateException
     {
@@ -876,11 +879,10 @@
         MessageDigest messageDigest = null;
         TSRequest tsQuery = null;
         try {
-            // SHA-1 is always used.
-            messageDigest = MessageDigest.getInstance("SHA-1");
+            messageDigest = MessageDigest.getInstance(tSADigestAlg);
             tsQuery = new TSRequest(tSAPolicyID, toBeTimestamped, messageDigest);
         } catch (NoSuchAlgorithmException e) {
-            // ignore
+            throw new IllegalArgumentException(e);
         }
 
         // Generate a nonce
@@ -908,9 +910,13 @@
         PKCS7 tsToken = tsReply.getToken();
 
         TimestampToken tst = tsReply.getTimestampToken();
-        if (!tst.getHashAlgorithm().getName().equals("SHA-1")) {
-            throw new IOException("Digest algorithm not SHA-1 in "
-                                  + "timestamp token");
+        try {
+            if (!tst.getHashAlgorithm().equals(AlgorithmId.get(tSADigestAlg))) {
+                throw new IOException("Digest algorithm not " + tSADigestAlg + " in "
+                                      + "timestamp token");
+            }
+        } catch (NoSuchAlgorithmException nase) {
+            throw new IllegalArgumentException();   // should have been caught before
         }
         if (!MessageDigest.isEqual(tst.getHashedMessage(),
                                    tsQuery.getHashedMessage())) {
diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/JarSignerParameters.java b/jdk/src/share/classes/sun/security/tools/jarsigner/JarSignerParameters.java
new file mode 100644
index 0000000..fe75f9d
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/JarSignerParameters.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.tools.jarsigner;
+
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.net.URI;
+import java.util.zip.*;
+
+import com.sun.jarsigner.ContentSignerParameters;
+
+class JarSignerParameters implements ContentSignerParameters {
+
+    private String[] args;
+    private URI tsa;
+    private X509Certificate tsaCertificate;
+    private byte[] signature;
+    private String signatureAlgorithm;
+    private X509Certificate[] signerCertificateChain;
+    private byte[] content;
+    private ZipFile source;
+    private String tSAPolicyID;
+    private String tSADigestAlg;
+
+    /**
+     * Create a new object.
+     */
+    JarSignerParameters(String[] args, URI tsa, X509Certificate tsaCertificate,
+        String tSAPolicyID, String tSADigestAlg,
+        byte[] signature, String signatureAlgorithm,
+        X509Certificate[] signerCertificateChain, byte[] content,
+        ZipFile source) {
+
+        if (signature == null || signatureAlgorithm == null ||
+            signerCertificateChain == null || tSADigestAlg == null) {
+            throw new NullPointerException();
+        }
+        this.args = args;
+        this.tsa = tsa;
+        this.tsaCertificate = tsaCertificate;
+        this.tSAPolicyID = tSAPolicyID;
+        this.tSADigestAlg = tSADigestAlg;
+        this.signature = signature;
+        this.signatureAlgorithm = signatureAlgorithm;
+        this.signerCertificateChain = signerCertificateChain;
+        this.content = content;
+        this.source = source;
+    }
+
+    /**
+     * Retrieves the command-line arguments.
+     *
+     * @return The command-line arguments. May be null.
+     */
+    public String[] getCommandLine() {
+        return args;
+    }
+
+    /**
+     * Retrieves the identifier for a Timestamping Authority (TSA).
+     *
+     * @return The TSA identifier. May be null.
+     */
+    public URI getTimestampingAuthority() {
+        return tsa;
+    }
+
+    /**
+     * Retrieves the certificate for a Timestamping Authority (TSA).
+     *
+     * @return The TSA certificate. May be null.
+     */
+    public X509Certificate getTimestampingAuthorityCertificate() {
+        return tsaCertificate;
+    }
+
+    public String getTSAPolicyID() {
+        return tSAPolicyID;
+    }
+
+    public String getTSADigestAlg() {
+        return tSADigestAlg;
+    }
+
+    /**
+     * Retrieves the signature.
+     *
+     * @return The non-null signature bytes.
+     */
+    public byte[] getSignature() {
+        return signature;
+    }
+
+    /**
+     * Retrieves the name of the signature algorithm.
+     *
+     * @return The non-null string name of the signature algorithm.
+     */
+    public String getSignatureAlgorithm() {
+        return signatureAlgorithm;
+    }
+
+    /**
+     * Retrieves the signer's X.509 certificate chain.
+     *
+     * @return The non-null array of X.509 public-key certificates.
+     */
+    public X509Certificate[] getSignerCertificateChain() {
+        return signerCertificateChain;
+    }
+
+    /**
+     * Retrieves the content that was signed.
+     *
+     * @return The content bytes. May be null.
+     */
+    public byte[] getContent() {
+        return content;
+    }
+
+    /**
+     * Retrieves the original source ZIP file before it was signed.
+     *
+     * @return The original ZIP file. May be null.
+     */
+    public ZipFile getSource() {
+        return source;
+    }
+}
diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
index 35f33c8..37b04c9 100644
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
@@ -139,6 +139,7 @@
     String tsaAlias; // alias for the Timestamping Authority's certificate
     String altCertChain; // file to read alternative cert chain from
     String tSAPolicyID;
+    String tSADigestAlg = "SHA-256";
     boolean verify = false; // verify the jar
     String verbose = null; // verbose output when signing/verifying
     boolean showcerts = false; // show certs when verifying
@@ -342,6 +343,9 @@
             } else if (collator.compare(flags, "-tsapolicyid") ==0) {
                 if (++n == args.length) usageNoArg();
                 tSAPolicyID = args[n];
+            } else if (collator.compare(flags, "-tsadigestalg") ==0) {
+                if (++n == args.length) usageNoArg();
+                tSADigestAlg = args[n];
             } else if (collator.compare(flags, "-debug") ==0) {
                 debug = true;
             } else if (collator.compare(flags, "-keypass") ==0) {
@@ -536,6 +540,9 @@
                 (".tsapolicyid.tsapolicyid.for.Timestamping.Authority"));
         System.out.println();
         System.out.println(rb.getString
+                (".tsadigestalg.algorithm.of.digest.data.in.timestamping.request"));
+        System.out.println();
+        System.out.println(rb.getString
                 (".altsigner.class.class.name.of.an.alternative.signing.mechanism"));
         System.out.println();
         System.out.println(rb.getString
@@ -1270,8 +1277,8 @@
             try {
                 block =
                     sf.generateBlock(privateKey, sigalg, certChain,
-                        externalSF, tsaUrl, tsaCert, tSAPolicyID, signingMechanism, args,
-                        zipFile);
+                        externalSF, tsaUrl, tsaCert, tSAPolicyID, tSADigestAlg,
+                        signingMechanism, args, zipFile);
             } catch (SocketTimeoutException e) {
                 // Provide a helpful message when TSA is beyond a firewall
                 error(rb.getString("unable.to.sign.jar.") +
@@ -2268,13 +2275,14 @@
                                boolean externalSF, String tsaUrl,
                                X509Certificate tsaCert,
                                String tSAPolicyID,
+                               String tSADigestAlg,
                                ContentSigner signingMechanism,
                                String[] args, ZipFile zipFile)
         throws NoSuchAlgorithmException, InvalidKeyException, IOException,
             SignatureException, CertificateException
     {
         return new Block(this, privateKey, sigalg, certChain, externalSF,
-                tsaUrl, tsaCert, tSAPolicyID, signingMechanism, args, zipFile);
+                tsaUrl, tsaCert, tSAPolicyID, tSADigestAlg, signingMechanism, args, zipFile);
     }
 
 
@@ -2288,8 +2296,8 @@
          */
         Block(SignatureFile sfg, PrivateKey privateKey, String sigalg,
             X509Certificate[] certChain, boolean externalSF, String tsaUrl,
-            X509Certificate tsaCert, String tSAPolicyID, ContentSigner signingMechanism,
-            String[] args, ZipFile zipFile)
+            X509Certificate tsaCert, String tSAPolicyID, String tSADigestAlg,
+            ContentSigner signingMechanism, String[] args, ZipFile zipFile)
             throws NoSuchAlgorithmException, InvalidKeyException, IOException,
             SignatureException, CertificateException {
 
@@ -2371,7 +2379,8 @@
 
             // Assemble parameters for the signing mechanism
             ContentSignerParameters params =
-                new JarSignerParameters(args, tsaUri, tsaCert, tSAPolicyID, signature,
+                new JarSignerParameters(args, tsaUri, tsaCert, tSAPolicyID,
+                        tSADigestAlg, signature,
                     signatureAlgorithm, certChain, content, zipFile);
 
             // Generate the signature block
@@ -2400,120 +2409,3 @@
         }
     }
 }
-
-
-/*
- * This object encapsulates the parameters used to perform content signing.
- */
-class JarSignerParameters implements ContentSignerParameters {
-
-    private String[] args;
-    private URI tsa;
-    private X509Certificate tsaCertificate;
-    private byte[] signature;
-    private String signatureAlgorithm;
-    private X509Certificate[] signerCertificateChain;
-    private byte[] content;
-    private ZipFile source;
-    private String tSAPolicyID;
-
-    /**
-     * Create a new object.
-     */
-    JarSignerParameters(String[] args, URI tsa, X509Certificate tsaCertificate,
-        String tSAPolicyID,
-        byte[] signature, String signatureAlgorithm,
-        X509Certificate[] signerCertificateChain, byte[] content,
-        ZipFile source) {
-
-        if (signature == null || signatureAlgorithm == null ||
-            signerCertificateChain == null) {
-            throw new NullPointerException();
-        }
-        this.args = args;
-        this.tsa = tsa;
-        this.tsaCertificate = tsaCertificate;
-        this.tSAPolicyID = tSAPolicyID;
-        this.signature = signature;
-        this.signatureAlgorithm = signatureAlgorithm;
-        this.signerCertificateChain = signerCertificateChain;
-        this.content = content;
-        this.source = source;
-    }
-
-    /**
-     * Retrieves the command-line arguments.
-     *
-     * @return The command-line arguments. May be null.
-     */
-    public String[] getCommandLine() {
-        return args;
-    }
-
-    /**
-     * Retrieves the identifier for a Timestamping Authority (TSA).
-     *
-     * @return The TSA identifier. May be null.
-     */
-    public URI getTimestampingAuthority() {
-        return tsa;
-    }
-
-    /**
-     * Retrieves the certificate for a Timestamping Authority (TSA).
-     *
-     * @return The TSA certificate. May be null.
-     */
-    public X509Certificate getTimestampingAuthorityCertificate() {
-        return tsaCertificate;
-    }
-
-    public String getTSAPolicyID() {
-        return tSAPolicyID;
-    }
-
-    /**
-     * Retrieves the signature.
-     *
-     * @return The non-null signature bytes.
-     */
-    public byte[] getSignature() {
-        return signature;
-    }
-
-    /**
-     * Retrieves the name of the signature algorithm.
-     *
-     * @return The non-null string name of the signature algorithm.
-     */
-    public String getSignatureAlgorithm() {
-        return signatureAlgorithm;
-    }
-
-    /**
-     * Retrieves the signer's X.509 certificate chain.
-     *
-     * @return The non-null array of X.509 public-key certificates.
-     */
-    public X509Certificate[] getSignerCertificateChain() {
-        return signerCertificateChain;
-    }
-
-    /**
-     * Retrieves the content that was signed.
-     *
-     * @return The content bytes. May be null.
-     */
-    public byte[] getContent() {
-        return content;
-    }
-
-    /**
-     * Retrieves the original source ZIP file before it was signed.
-     *
-     * @return The original ZIP file. May be null.
-     */
-    public ZipFile getSource() {
-        return source;
-    }
-}
diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java b/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
index 77b0628..db35b1e 100644
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
@@ -88,6 +88,8 @@
                 "[-tsacert <alias>]          public key certificate for Timestamping Authority"},
         {".tsapolicyid.tsapolicyid.for.Timestamping.Authority",
                 "[-tsapolicyid <oid>]        TSAPolicyID for Timestamping Authority"},
+        {".tsadigestalg.algorithm.of.digest.data.in.timestamping.request",
+                "[-tsadigestalg <algorithm>] algorithm of digest data in timestamping request"},
         {".altsigner.class.class.name.of.an.alternative.signing.mechanism",
                 "[-altsigner <class>]        class name of an alternative signing mechanism"},
         {".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism",
diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java b/jdk/src/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java
index 3e50419..c149f8b 100644
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java
@@ -132,9 +132,14 @@
                 }
             }
         }
+        String tSADigestAlg = "SHA-256";
+        if (params instanceof JarSignerParameters) {
+            tSADigestAlg = ((JarSignerParameters)params).getTSADigestAlg();
+        }
         return PKCS7.generateSignedData(signature, signerChain, content,
                                         params.getSignatureAlgorithm(), tsaURI,
-                                        params.getTSAPolicyID());
+                                        params.getTSAPolicyID(),
+                                        tSADigestAlg);
     }
 
     /**
diff --git a/jdk/src/windows/classes/sun/security/mscapi/KeyStore.java b/jdk/src/windows/classes/sun/security/mscapi/KeyStore.java
index abaa2e3..cbf4240 100644
--- a/jdk/src/windows/classes/sun/security/mscapi/KeyStore.java
+++ b/jdk/src/windows/classes/sun/security/mscapi/KeyStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -189,8 +189,10 @@
 
     /*
      * The keystore entries.
+     * Keys in the map are unique aliases (thus can differ from
+     * KeyEntry.getAlias())
      */
-    private Collection<KeyEntry> entries = new ArrayList<KeyEntry>();
+    private Map<String,KeyEntry> entries = new HashMap<>();
 
     /*
      * The keystore name.
@@ -250,13 +252,10 @@
         if (engineIsKeyEntry(alias) == false)
             return null;
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
-                return entry.getPrivateKey();
-            }
-        }
-
-        return null;
+        KeyEntry entry = entries.get(alias);
+        return (entry == null)
+                ? null
+                : entry.getPrivateKey();
     }
 
     /**
@@ -276,15 +275,13 @@
             return null;
         }
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
-                X509Certificate[] certChain = entry.getCertificateChain();
-
-                return certChain.clone();
-            }
-        }
-
-        return null;
+        KeyEntry entry = entries.get(alias);
+        X509Certificate[] certChain = (entry == null)
+                ? null
+                : entry.getCertificateChain();
+        return (certChain == null)
+                ? null
+                : certChain.clone();
     }
 
     /**
@@ -308,15 +305,13 @@
             return null;
         }
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias()))
-            {
-                X509Certificate[] certChain = entry.getCertificateChain();
-                return certChain.length == 0 ? null : certChain[0];
-            }
-        }
-
-        return null;
+        KeyEntry entry = entries.get(alias);
+        X509Certificate[] certChain = (entry == null)
+                ? null
+                : entry.getCertificateChain();
+        return (certChain == null || certChain.length == 0)
+                ? null
+                : certChain[0];
     }
 
     /**
@@ -380,29 +375,32 @@
 
         if (key instanceof RSAPrivateCrtKey) {
 
-            KeyEntry entry = null;
-            boolean found = false;
+            KeyEntry entry = entries.get(alias);
 
-            for (KeyEntry e : entries) {
-                if (alias.equals(e.getAlias())) {
-                    found = true;
-                    entry = e;
-                    break;
+            X509Certificate[] xchain;
+            if (chain != null) {
+                if (chain instanceof X509Certificate[]) {
+                    xchain = (X509Certificate[]) chain;
+                } else {
+                    xchain = new X509Certificate[chain.length];
+                    System.arraycopy(chain, 0, xchain, 0, chain.length);
                 }
+            } else {
+                xchain = null;
             }
 
-            if (! found) {
+            if (entry == null) {
                 entry =
                     //TODO new KeyEntry(alias, key, (X509Certificate[]) chain);
-                    new KeyEntry(alias, null, (X509Certificate[]) chain);
-                entries.add(entry);
+                    new KeyEntry(alias, null, xchain);
+                storeWithUniqueAlias(alias, entry);
             }
 
             entry.setAlias(alias);
 
             try {
                 entry.setPrivateKey((RSAPrivateCrtKey) key);
-                entry.setCertificateChain((X509Certificate[]) chain);
+                entry.setCertificateChain(xchain);
 
             } catch (CertificateException ce) {
                 throw new KeyStoreException(ce);
@@ -474,23 +472,14 @@
             // TODO - build CryptoAPI chain?
             X509Certificate[] chain =
                 new X509Certificate[]{ (X509Certificate) cert };
-            KeyEntry entry = null;
-            boolean found = false;
+            KeyEntry entry = entries.get(alias);
 
-            for (KeyEntry e : entries) {
-                if (alias.equals(e.getAlias())) {
-                    found = true;
-                    entry = e;
-                    break;
-                }
-            }
-
-            if (! found) {
+            if (entry == null) {
                 entry =
                     new KeyEntry(alias, null, chain);
-                entries.add(entry);
-
+                storeWithUniqueAlias(alias, entry);
             }
+
             if (entry.getPrivateKey() == null) { // trusted-cert entry
                 entry.setAlias(alias);
 
@@ -522,32 +511,26 @@
             throw new KeyStoreException("alias must not be null");
         }
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
+        KeyEntry entry = entries.remove(alias);
+        if (entry != null) {
+            // Get end-entity certificate and remove from system cert store
+            X509Certificate[] certChain = entry.getCertificateChain();
+            if (certChain != null) {
 
-                // Get end-entity certificate and remove from system cert store
-                X509Certificate[] certChain = entry.getCertificateChain();
-                if (certChain != null) {
+                try {
 
-                    try {
-
-                        byte[] encoding = certChain[0].getEncoded();
-                        removeCertificate(getName(), alias, encoding,
+                    byte[] encoding = certChain[0].getEncoded();
+                    removeCertificate(getName(), entry.getAlias(), encoding,
                             encoding.length);
 
-                    } catch (CertificateException e) {
-                        throw new KeyStoreException("Cannot remove entry: " +
-                            e);
-                    }
+                } catch (CertificateException e) {
+                    throw new KeyStoreException("Cannot remove entry: ", e);
                 }
-                Key privateKey = entry.getPrivateKey();
-                if (privateKey != null) {
-                    destroyKeyContainer(
-                        Key.getContainerName(privateKey.getHCryptProvider()));
-                }
-
-                entries.remove(entry);
-                break;
+            }
+            Key privateKey = entry.getPrivateKey();
+            if (privateKey != null) {
+                destroyKeyContainer(
+                    Key.getContainerName(privateKey.getHCryptProvider()));
             }
         }
     }
@@ -558,8 +541,7 @@
      * @return enumeration of the alias names
      */
     public Enumeration<String> engineAliases() {
-
-        final Iterator<KeyEntry> iter = entries.iterator();
+        final Iterator<String> iter = entries.keySet().iterator();
 
         return new Enumeration<String>()
         {
@@ -570,8 +552,7 @@
 
             public String nextElement()
             {
-                KeyEntry entry = iter.next();
-                return entry.getAlias();
+                return iter.next();
             }
         };
     }
@@ -584,15 +565,7 @@
      * @return true if the alias exists, false otherwise
      */
     public boolean engineContainsAlias(String alias) {
-        for (Enumeration<String> enumerator = engineAliases();
-            enumerator.hasMoreElements();)
-        {
-            String a = enumerator.nextElement();
-
-            if (a.equals(alias))
-                return true;
-        }
-        return false;
+        return entries.containsKey(alias);
     }
 
     /**
@@ -617,13 +590,8 @@
             return false;
         }
 
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
-                return entry.getPrivateKey() != null;
-            }
-        }
-
-        return false;
+        KeyEntry entry = entries.get(alias);
+        return entry != null && entry.getPrivateKey() != null;
     }
 
     /**
@@ -633,15 +601,14 @@
      * @return true if the entry identified by the given alias is a
      * <i>trusted certificate entry</i>, false otherwise.
      */
-    public boolean engineIsCertificateEntry(String alias)
-    {
-        for (KeyEntry entry : entries) {
-            if (alias.equals(entry.getAlias())) {
-                return entry.getPrivateKey() == null;
-            }
+    public boolean engineIsCertificateEntry(String alias) {
+
+        if (alias == null) {
+            return false;
         }
 
-        return false;
+        KeyEntry entry = entries.get(alias);
+        return entry != null && entry.getPrivateKey() == null;
     }
 
     /**
@@ -660,9 +627,10 @@
      * @return the (alias) name of the first entry with matching certificate,
      * or null if no such entry exists in this keystore.
      */
-    public String engineGetCertificateAlias(Certificate cert)
-    {
-        for (KeyEntry entry : entries) {
+    public String engineGetCertificateAlias(Certificate cert) {
+
+        for (Map.Entry<String,KeyEntry> mapEntry : entries.entrySet()) {
+            KeyEntry entry = mapEntry.getValue();
             if (entry.certChain != null && entry.certChain[0].equals(cert)) {
                 return entry.getAlias();
             }
@@ -755,7 +723,7 @@
         try {
 
             // Load keys and/or certificate chains
-            loadKeysOrCertificateChains(getName(), entries);
+            loadKeysOrCertificateChains(getName());
 
         } catch (KeyStoreException e) {
             throw new IOException(e);
@@ -763,12 +731,31 @@
     }
 
     /**
+     * Stores the given entry into the map, making sure
+     * the alias, used as the key is unique.
+     * If the same alias already exists, it tries to append
+     * a suffix  (1), (2), etc to it until it finds a unique
+     * value.
+     */
+    private void storeWithUniqueAlias(String alias, KeyEntry entry) {
+        String uniqAlias = alias;
+        int uniqNum = 1;
+
+        while (true) {
+            if (entries.putIfAbsent(uniqAlias, entry) == null) {
+                break;
+            }
+            uniqAlias = alias + " (" + (uniqNum++) + ")";
+        }
+    }
+
+
+    /**
      * Generates a certificate chain from the collection of
      * certificates and stores the result into a key entry.
      */
     private void generateCertificateChain(String alias,
-        Collection<? extends Certificate> certCollection,
-        Collection<KeyEntry> entries)
+        Collection<? extends Certificate> certCollection)
     {
         try
         {
@@ -782,10 +769,8 @@
                 certChain[i] = (X509Certificate) iter.next();
             }
 
-            KeyEntry entry = new KeyEntry(alias, null, certChain);
-
-            // Add cert chain
-            entries.add(entry);
+            storeWithUniqueAlias(alias,
+                    new KeyEntry(alias, null, certChain));
         }
         catch (Throwable e)
         {
@@ -800,8 +785,7 @@
      */
     private void generateRSAKeyAndCertificateChain(String alias,
         long hCryptProv, long hCryptKey, int keyLength,
-        Collection<? extends Certificate> certCollection,
-        Collection<KeyEntry> entries)
+        Collection<? extends Certificate> certCollection)
     {
         try
         {
@@ -815,11 +799,9 @@
                 certChain[i] = (X509Certificate) iter.next();
             }
 
-            KeyEntry entry = new KeyEntry(alias, new RSAPrivateKey(hCryptProv,
-                hCryptKey, keyLength), certChain);
-
-            // Add cert chain
-            entries.add(entry);
+            storeWithUniqueAlias(alias, new KeyEntry(alias,
+                    new RSAPrivateKey(hCryptProv, hCryptKey, keyLength),
+                    certChain));
         }
         catch (Throwable e)
         {
@@ -876,8 +858,8 @@
      * @param name Name of keystore.
      * @param entries Collection of key/certificate.
      */
-    private native void loadKeysOrCertificateChains(String name,
-        Collection<KeyEntry> entries) throws KeyStoreException;
+    private native void loadKeysOrCertificateChains(String name)
+            throws KeyStoreException;
 
     /**
      * Stores a DER-encoded certificate into the certificate store
diff --git a/jdk/src/windows/native/sun/security/mscapi/security.cpp b/jdk/src/windows/native/sun/security/mscapi/security.cpp
index 161c2ae..553dd42 100644
--- a/jdk/src/windows/native/sun/security/mscapi/security.cpp
+++ b/jdk/src/windows/native/sun/security/mscapi/security.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -266,7 +266,7 @@
  * Signature: (Ljava/lang/String;Ljava/util/Collection;)V
  */
 JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateChains
-  (JNIEnv *env, jobject obj, jstring jCertStoreName, jobject jCollections)
+  (JNIEnv *env, jobject obj, jstring jCertStoreName)
 {
     /**
      * Certificate in cert store has enhanced key usage extension
@@ -325,7 +325,7 @@
         // Determine method ID to generate certificate chain
         jmethodID mGenCertChain = env->GetMethodID(clazzOfThis,
                                                    "generateCertificateChain",
-                                                   "(Ljava/lang/String;Ljava/util/Collection;Ljava/util/Collection;)V");
+                                                   "(Ljava/lang/String;Ljava/util/Collection;)V");
         if (mGenCertChain == NULL) {
             __leave;
         }
@@ -333,7 +333,7 @@
         // Determine method ID to generate RSA certificate chain
         jmethodID mGenRSAKeyAndCertChain = env->GetMethodID(clazzOfThis,
                                                    "generateRSAKeyAndCertificateChain",
-                                                   "(Ljava/lang/String;JJILjava/util/Collection;Ljava/util/Collection;)V");
+                                                   "(Ljava/lang/String;JJILjava/util/Collection;)V");
         if (mGenRSAKeyAndCertChain == NULL) {
             __leave;
         }
@@ -360,38 +360,37 @@
             } else {
                 // Private key is available
 
-            BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
+                BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
 
-            // Skip certificate if cannot find private key
-            if (bGetUserKey == FALSE)
-            {
-                if (bCallerFreeProv)
-                    ::CryptReleaseContext(hCryptProv, NULL);
+                // Skip certificate if cannot find private key
+                if (bGetUserKey == FALSE)
+                {
+                    if (bCallerFreeProv)
+                        ::CryptReleaseContext(hCryptProv, NULL);
 
-                continue;
+                    continue;
+                }
+
+                // Set cipher mode to ECB
+                DWORD dwCipherMode = CRYPT_MODE_ECB;
+                ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
+
+
+                // If the private key is present in smart card, we may not be able to
+                // determine the key length by using the private key handle. However,
+                // since public/private key pairs must have the same length, we could
+                // determine the key length of the private key by using the public key
+                // in the certificate.
+                dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+                        &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
+
             }
-
-            // Set cipher mode to ECB
-            DWORD dwCipherMode = CRYPT_MODE_ECB;
-            ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
-
-
-            // If the private key is present in smart card, we may not be able to
-            // determine the key length by using the private key handle. However,
-            // since public/private key pairs must have the same length, we could
-            // determine the key length of the private key by using the public key
-            // in the certificate.
-            dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
-                                                               &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
-
-}
             PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
 
             // Build certificate chain by using system certificate store.
             // Add cert chain into collection for any key usage.
             //
-            if (GetCertificateChain(OID_EKU_ANY, pCertContext,
-                &pCertChainContext))
+            if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))
             {
 
                 for (unsigned int i=0; i < pCertChainContext->cChain; i++)
@@ -450,26 +449,26 @@
                         // collection
                         env->CallVoidMethod(obj, mGenCertChain,
                             env->NewStringUTF(pszNameString),
-                            jArrayList, jCollections);
+                            jArrayList);
                     }
                     else
                     {
-                    // Determine key type: RSA or DSA
-                    DWORD dwData = CALG_RSA_KEYX;
-                    DWORD dwSize = sizeof(DWORD);
-                    ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData,
-                        &dwSize, NULL);
+                        // Determine key type: RSA or DSA
+                        DWORD dwData = CALG_RSA_KEYX;
+                        DWORD dwSize = sizeof(DWORD);
+                        ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData,
+                                &dwSize, NULL);
 
-                    if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
-                    {
-                        // Generate RSA certificate chain and store into cert
-                        // chain collection
-                        env->CallVoidMethod(obj, mGenRSAKeyAndCertChain,
-                            env->NewStringUTF(pszNameString),
-                            (jlong) hCryptProv, (jlong) hUserKey,
-                            dwPublicKeyLength, jArrayList, jCollections);
+                        if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
+                        {
+                            // Generate RSA certificate chain and store into cert
+                            // chain collection
+                            env->CallVoidMethod(obj, mGenRSAKeyAndCertChain,
+                                    env->NewStringUTF(pszNameString),
+                                    (jlong) hCryptProv, (jlong) hUserKey,
+                                    dwPublicKeyLength, jArrayList);
+                        }
                     }
-}
                 }
 
                 // Free cert chain
diff --git a/jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java b/jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java
similarity index 77%
rename from jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java
rename to jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java
index 190390d..3c42ec7 100644
--- a/jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java
+++ b/jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,6 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 import java.awt.BorderLayout;
 import java.awt.Point;
 import java.awt.Robot;
@@ -29,22 +30,23 @@
 import javax.swing.JScrollPane;
 import javax.swing.JTextArea;
 import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
+
 import sun.awt.OSInfo;
 
 /**
  * @test
- * @bug 8033000
+ * @bug 8033000 8147994
  * @author Alexander Scherbatiy
  * @summary No Horizontal Mouse Wheel Support In BasicScrollPaneUI
- * @run main bug8033000
+ * @run main HorizontalMouseWheelOnShiftPressed
  */
-public class bug8033000 {
+public class HorizontalMouseWheelOnShiftPressed {
 
     private static JScrollPane scrollPane;
     private static JTextArea textArea;
     private static Point point;
     private static final int delta;
+    private static JFrame frame;
 
     static {
         delta = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ? -30 : 30;
@@ -55,9 +57,17 @@
         Robot robot = new Robot();
         robot.setAutoDelay(50);
 
-        SwingUtilities.invokeAndWait(bug8033000::createAndShowGUI);
+        SwingUtilities.invokeAndWait(
+                HorizontalMouseWheelOnShiftPressed::createAndShowGUI);
         robot.waitForIdle();
+        try {
+            test(robot);
+        } finally {
+            frame.dispose();
+        }
+    }
 
+    private static void test(Robot robot) throws Exception {
         SwingUtilities.invokeAndWait(() -> {
             Point locationOnScreen = scrollPane.getLocationOnScreen();
             point = new Point(
@@ -73,7 +83,7 @@
         robot.waitForIdle();
         robot.mouseWheel(delta);
         robot.waitForIdle();
-        checkScrollPane(true);
+        checkScrollPane(true, false);
 
         // vertical scroll bar is enabled + shift
         initScrollPane(true, false);
@@ -82,14 +92,14 @@
         robot.mouseWheel(delta);
         robot.keyRelease(KeyEvent.VK_SHIFT);
         robot.waitForIdle();
-        checkScrollPane(true);
+        checkScrollPane(false, false);
 
         // horizontal scroll bar is enabled
         initScrollPane(false, true);
         robot.waitForIdle();
         robot.mouseWheel(delta);
         robot.waitForIdle();
-        checkScrollPane(false);
+        checkScrollPane(false, true);
 
         // horizontal scroll bar is enabled + shift
         initScrollPane(false, true);
@@ -98,14 +108,14 @@
         robot.mouseWheel(delta);
         robot.keyRelease(KeyEvent.VK_SHIFT);
         robot.waitForIdle();
-        checkScrollPane(false);
+        checkScrollPane(false, true);
 
         // both scroll bars are enabled
         initScrollPane(true, true);
         robot.waitForIdle();
         robot.mouseWheel(delta);
         robot.waitForIdle();
-        checkScrollPane(true);
+        checkScrollPane(true, false);
 
         // both scroll bars are enabled + shift
         initScrollPane(true, true);
@@ -114,7 +124,7 @@
         robot.mouseWheel(delta);
         robot.keyRelease(KeyEvent.VK_SHIFT);
         robot.waitForIdle();
-        checkScrollPane(false);
+        checkScrollPane(false, true);
     }
 
     static void initScrollPane(boolean vVisible, boolean hVisible) throws Exception {
@@ -129,17 +139,25 @@
         });
     }
 
-    static void checkScrollPane(boolean verticalScrolled) throws Exception {
+    static void checkScrollPane(boolean verticalScrolled,
+                                boolean horizontalScrolled) throws Exception {
         SwingUtilities.invokeAndWait(() -> {
 
             if (verticalScrolled) {
-                if (scrollPane.getVerticalScrollBar().getValue() == 0
-                        || scrollPane.getHorizontalScrollBar().getValue() != 0) {
+                if (scrollPane.getVerticalScrollBar().getValue() == 0) {
                     throw new RuntimeException("Wrong vertical scrolling!");
                 }
+            } else{
+                if (scrollPane.getVerticalScrollBar().getValue() != 0) {
+                    throw new RuntimeException("Wrong vertical scrolling!");
+                }
+            }
+            if (horizontalScrolled) {
+                if (scrollPane.getHorizontalScrollBar().getValue() == 0) {
+                    throw new RuntimeException("Wrong horizontal scrolling!");
+                }
             } else {
-                if (scrollPane.getVerticalScrollBar().getValue() != 0
-                        || scrollPane.getHorizontalScrollBar().getValue() == 0) {
+                if (scrollPane.getHorizontalScrollBar().getValue() != 0) {
                     throw new RuntimeException("Wrong horizontal scrolling!");
                 }
             }
@@ -147,9 +165,10 @@
     }
 
     static void createAndShowGUI() {
-        JFrame frame = new JFrame();
+        frame = new JFrame();
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setSize(300, 300);
+        frame.setLocationRelativeTo(null);
         textArea = new JTextArea("Hello World!");
         scrollPane = new JScrollPane(textArea);
         JPanel panel = new JPanel(new BorderLayout());
diff --git a/jdk/test/sun/security/mscapi/CastError.java b/jdk/test/sun/security/mscapi/CastError.java
new file mode 100644
index 0000000..439ba24
--- /dev/null
+++ b/jdk/test/sun/security/mscapi/CastError.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+
+/**
+ * @test
+ * @bug 8143913
+ * @requires os.family == "windows"
+ * @summary MSCAPI keystore should accept Certificate[] in setEntry()
+ */
+
+public class CastError {
+    public static void main(String[] args) throws Exception {
+        KeyStore ks = KeyStore.getInstance("JKS");
+        FileInputStream fis = new FileInputStream(
+                new File(System.getProperty("test.src"),
+                        "../tools/jarsigner/JarSigning.keystore"));
+        ks.load(fis, "bbbbbb".toCharArray());
+
+        PrivateKey pk = (PrivateKey) ks.getKey("c", "bbbbbb".toCharArray());
+        Certificate cert = ks.getCertificate("c");
+
+        ks = KeyStore.getInstance("Windows-MY");
+        ks.load(null, null);
+
+        ks.setKeyEntry("8143913", pk, null, new Certificate[]{cert});
+        ks.deleteEntry("8143913");
+    }
+}
diff --git a/jdk/test/sun/security/mscapi/nonUniqueAliases/NonUniqueAliases.sh b/jdk/test/sun/security/mscapi/nonUniqueAliases/NonUniqueAliases.sh
new file mode 100644
index 0000000..b6e264c
--- /dev/null
+++ b/jdk/test/sun/security/mscapi/nonUniqueAliases/NonUniqueAliases.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+
+# @test
+# @ignore Uses certutil.exe that isn't guaranteed to be installed
+# @bug 6483657
+# @requires os.family == "windows"
+# @run shell NonUniqueAliases.sh
+# @summary Test "keytool -list" displays correcly same named certificates
+
+# set a few environment variables so that the shell-script can run stand-alone
+# in the source directory
+if [ "${TESTSRC}" = "" ] ; then
+   TESTSRC="."
+fi
+
+if [ "${TESTCLASSES}" = "" ] ; then
+   TESTCLASSES="."
+fi
+
+if [ "${TESTJAVA}" = "" ] ; then
+   echo "TESTJAVA not set.  Test cannot execute."
+   echo "FAILED!!!"
+   exit 1
+fi
+
+OS=`uname -s`
+case "$OS" in
+    Windows* | CYGWIN* )
+
+        # 'uname -m' does not give us enough information -
+        #  should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk),
+        #  but JTREG does not pass this env variable when executing a shell script.
+        #
+        #  execute test program - rely on it to exit if platform unsupported
+
+        echo "removing the alias NonUniqueName if it already exists"
+        certutil -user -delstore MY NonUniqueName
+
+        echo "Importing 1st certificate into MY keystore using certutil tool"
+        certutil -user -addstore MY ${TESTSRC}/nonUniq1.pem
+
+        echo "Importing 2nd certificate into MY keystore using certutil tool"
+        certutil -user -addstore MY ${TESTSRC}/nonUniq2.pem
+
+        echo "Listing certificates with keytool"
+        ${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -list -storetype Windows-My
+
+        echo "Counting expected entries"
+        count0=`${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -list -storetype Windows-My | grep 'NonUniqueName,' | wc -l`
+
+        if [ ! $count0 = 1 ]; then
+            echo "error: unexpected number of entries ($count0) in the Windows-MY store"
+            certutil -user -delstore MY NonUniqueName
+            exit 115
+        fi
+
+        echo "Counting expected entries"
+        count1=`${TESTJAVA}/bin/keytool ${TESTTOOLVMOPTS} -list -storetype Windows-My | grep 'NonUniqueName (1),' | wc -l`
+
+        if [ ! $count1 = 1 ]; then
+            echo "error: unexpected number of entries ($count1) in the Windows-MY store"
+            certutil -user -delstore MY NonUniqueName
+            exit 116
+        fi
+
+        echo "Cleaning up"
+        certutil -user -delstore MY NonUniqueName
+
+        exit 0
+        ;;
+
+    * )
+        echo "This test is not intended for '$OS' - passing test"
+        exit 0
+        ;;
+esac
diff --git a/jdk/test/sun/security/mscapi/nonUniqueAliases/nonUniq1.pem b/jdk/test/sun/security/mscapi/nonUniqueAliases/nonUniq1.pem
new file mode 100644
index 0000000..73ed657
--- /dev/null
+++ b/jdk/test/sun/security/mscapi/nonUniqueAliases/nonUniq1.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAWegAwIBAgIJANy5XBGM4BSuMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV
+BAMMDU5vblVuaXF1ZU5hbWUwHhcNMTYwNDAxMTcyMjQ0WhcNMTYwNzEwMTcyMjQ0
+WjAYMRYwFAYDVQQDDA1Ob25VbmlxdWVOYW1lMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDI0hlED2YFVgTaVLKWvsqB9JN9EJpUWECkB97fJwb1x99dHf0TO2p6
+HPPvkvjBiAMEZYbojCz+WpNhG1Ilu/UgKwPyHh1pL6kRcEhlS2G3i7p9SDLHWlk0
+xfdhSZERgd6ROpDnY7eaj1CTdVCSyEATs4FFyNtN9Q39jyeCU++ksQIDAQABo1Aw
+TjAdBgNVHQ4EFgQUpW/Wtw/OOTdnFTL7afIkNjuCVr8wHwYDVR0jBBgwFoAUpW/W
+tw/OOTdnFTL7afIkNjuCVr8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOB
+gQAWC+xX1cGNNp3F6dAb5tKKJGgQwsjfrjDP0/AirWc7Im1kTCpVPT61Ayt0bHgH
+n3hGivKmO7ChQAI3QsDMDKWE98tF6afPltBOoWh2a9tPd65JSD1HfkG+Wc1IZ5gL
+8rKp1tdKTEG2A+qXRN/e6DdtMsgDrK1iPfX+rer53TC+Yg==
+-----END CERTIFICATE-----
diff --git a/jdk/test/sun/security/mscapi/nonUniqueAliases/nonUniq2.pem b/jdk/test/sun/security/mscapi/nonUniqueAliases/nonUniq2.pem
new file mode 100644
index 0000000..ac4d1a7
--- /dev/null
+++ b/jdk/test/sun/security/mscapi/nonUniqueAliases/nonUniq2.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAWegAwIBAgIJAPyQune5t/SZMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV
+BAMMDU5vblVuaXF1ZU5hbWUwHhcNMTYwNDAxMTcyMzI0WhcNMTYwNzEwMTcyMzI0
+WjAYMRYwFAYDVQQDDA1Ob25VbmlxdWVOYW1lMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDeSu/pPzL9hA1kjA2Rs13LpN2lNrisbYg/Vj/swGDMJnVCzS3IFQQy
+71515mru+ngrHnfPSo4FKUhZPJzET2D7CruR65SzhQ96SHGoR8rhmL41KRBKELuR
+3MoarLFziFzeIil4NZg55xp6TE/WCXRfi7HNdIgoKQGLoIhehVGN8QIDAQABo1Aw
+TjAdBgNVHQ4EFgQUxFw79pLSf5Ul3zLqi/Mc6pSxEtswHwYDVR0jBBgwFoAUxFw7
+9pLSf5Ul3zLqi/Mc6pSxEtswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOB
+gQDPilBcFpFrjwqb+lJxDxXK992KjNUS8yFLo1DQ/LBTaoHvy/U5zxzRq+nvSaaf
+h+RIKqTwIbuBhSjrXVdJ/gzob/UlPC7IDo7FVbZwOHqTkqEum8jQEpX67hEevw9s
++reyqGhLsCtQK6uBTd2Nt9uOVCHrWNzWgQewkVYAUM5QpA==
+-----END CERTIFICATE-----
diff --git a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
index 65b1cca..113bb26 100644
--- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
+++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
@@ -24,10 +24,9 @@
 import com.sun.net.httpserver.*;
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
-import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.math.BigInteger;
@@ -38,9 +37,15 @@
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Calendar;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import sun.misc.IOUtils;
 import sun.security.pkcs.ContentInfo;
 import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.PKCS9Attribute;
 import sun.security.pkcs.SignerInfo;
+import sun.security.timestamp.TimestampToken;
 import sun.security.util.DerOutputStream;
 import sun.security.util.DerValue;
 import sun.security.util.ObjectIdentifier;
@@ -51,6 +56,8 @@
     static final String TSKS = "tsks";
     static final String JAR = "old.jar";
 
+    static final String defaultPolicyId = "2.3.4.5";
+
     static class Handler implements HttpHandler {
         public void handle(HttpExchange t) throws IOException {
             int len = 0;
@@ -94,6 +101,11 @@
          * 6: extension is missing
          * 7: extension is non-critical
          * 8: extension does not have timestamping
+         * 9: no cert in response
+         * 10: normal
+         * 11: always return default policy id
+         * 12: normal
+         * otherwise: normal
          * @returns the signed
          */
         byte[] sign(byte[] input, int path) throws Exception {
@@ -106,6 +118,7 @@
                     messageImprint.data.getDerValue());
             System.err.println("AlgorithmId: " + aid);
 
+            ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId);
             BigInteger nonce = null;
             while (value.data.available() > 0) {
                 DerValue v = value.data.getDerValue();
@@ -114,6 +127,9 @@
                     System.err.println("nonce: " + nonce);
                 } else if (v.tag == DerValue.tag_Boolean) {
                     System.err.println("certReq: " + v.getBoolean());
+                } else if (v.tag == DerValue.tag_ObjectId) {
+                    policyId = v.getOID();
+                    System.err.println("PolicyID: " + policyId);
                 }
             }
 
@@ -127,6 +143,10 @@
             if (path == 7) alias = "tsbad2";
             if (path == 8) alias = "tsbad3";
 
+            if (path == 11) {
+                policyId = new ObjectIdentifier(defaultPolicyId);
+            }
+
             DerOutputStream statusInfo = new DerOutputStream();
             statusInfo.putInteger(0);
 
@@ -150,7 +170,7 @@
             DerOutputStream tst = new DerOutputStream();
 
             tst.putInteger(1);
-            tst.putOID(new ObjectIdentifier("1.2.3.4"));    // policy
+            tst.putOID(policyId);
 
             if (path != 3 && path != 4) {
                 tst.putDerValue(messageImprint);
@@ -260,15 +280,43 @@
                 jarsigner(cmd, 7, false);   // tsbad2
                 jarsigner(cmd, 8, false);   // tsbad3
                 jarsigner(cmd, 9, false);   // no cert in timestamp
-                jarsigner(cmd + " -tsapolicyid 1.2.3.4", 0, true);
-                jarsigner(cmd + " -tsapolicyid 1.2.3.5", 0, false);
+                jarsigner(cmd + " -tsapolicyid 1.2.3.4", 10, true);
+                checkTimestamp("new_10.jar", "1.2.3.4", "SHA-256");
+                jarsigner(cmd + " -tsapolicyid 1.2.3.5", 11, false);
+                jarsigner(cmd + " -tsadigestalg SHA", 12, true);
+                checkTimestamp("new_12.jar", defaultPolicyId, "SHA-1");
             } else {                        // Run as a standalone server
                 System.err.println("Press Enter to quit server");
                 System.in.read();
             }
         } finally {
             server.stop(0);
-            new File("x.jar").delete();
+        }
+    }
+
+    static void checkTimestamp(String file, String policyId, String digestAlg)
+            throws Exception {
+        try (JarFile jf = new JarFile(file)) {
+            JarEntry je = jf.getJarEntry("META-INF/OLD.RSA");
+            try (InputStream is = jf.getInputStream(je)) {
+                byte[] content = IOUtils.readFully(is, -1, true);
+                PKCS7 p7 = new PKCS7(content);
+                SignerInfo[] si = p7.getSignerInfos();
+                if (si == null || si.length == 0) {
+                    throw new Exception("Not signed");
+                }
+                PKCS9Attribute p9 = si[0].getUnauthenticatedAttributes()
+                        .getAttribute(PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
+                PKCS7 tsToken = new PKCS7((byte[]) p9.getValue());
+                TimestampToken tt =
+                        new TimestampToken(tsToken.getContentInfo().getData());
+                if (!tt.getHashAlgorithm().toString().equals(digestAlg)) {
+                    throw new Exception("Digest alg different");
+                }
+                if (!tt.getPolicyID().equals(policyId)) {
+                    throw new Exception("policyId different");
+                }
+            }
         }
     }
 
diff --git a/jdk/test/sun/security/tools/jarsigner/ts.sh b/jdk/test/sun/security/tools/jarsigner/ts.sh
index 928b22e..6cee680 100644
--- a/jdk/test/sun/security/tools/jarsigner/ts.sh
+++ b/jdk/test/sun/security/tools/jarsigner/ts.sh
@@ -86,6 +86,6 @@
         $KT -alias ca -gencert -ext eku:critical=cs | \
         $KT -alias tsbad3 -importcert
 
-$JAVAC -d . ${TESTSRC}/TimestampCheck.java
+$JAVAC -XDignore.symbol.file -d . ${TESTSRC}/TimestampCheck.java
 $JAVA ${TESTVMOPTS} TimestampCheck
 
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index b0149ea..7a86bdd 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -519,12 +519,20 @@
 81e48503b62fd8814135f642905fe38056aaf2a9 jdk8u72-b13
 e48d06eeff82bea512cea44fa14d59b88067ef83 jdk8u72-b14
 769b21d1b85cfb57c11c89bbc8f185f9e520df66 jdk8u72-b15
+c90794ad4d12eeeae5d9bbfce65fa0043a313548 jdk8u72-b31
 e9b46178f2e35d9ed2cd5b2f7279cf5e4e954222 jdk8u73-b00
 eeb5306edb7a0140117fe346782cce19c4c562a7 jdk8u73-b01
 955689d050b9f3f61b90ca063fe13704a82f5394 jdk8u73-b02
 2a36c3c61f905c5b389ae1d62f446e57f96be3a2 jdk8u74-b00
 ae6c74c1197afcbd83d393aa6f96221d759022a2 jdk8u74-b01
 3107cf87696f0516d6f5fa7cdc416069e2800d02 jdk8u74-b02
+4608bbcc94f73059680acd0f486744ff26485ee9 jdk8u74-b31
+7d0f4c8fc2754e25c1c148ff47bb79aa880c2874 jdk8u74-b32
+7bce03d47545e6a5341a2722168cd6bf697c4132 jdk8u77-b00
+678b645aa10aaf27895c87872c399c15daa026a1 jdk8u77-b01
+09abd795d1d143933224bcb3f12f5d4686b65373 jdk8u77-b02
+b6ee21a35619ce4d3b46a9b825438a3bc9bb63cd jdk8u77-b03
+961f73438a3cdacc6197663b2495b73c08805f24 jdk8u77-b31
 c90794ad4d12eeeae5d9bbfce65fa0043a313548 jdk8u72-b31
 c7eddafb2ee2cc9d62f20c4d821ccac03bd4617d jdk8u75-b00
 69fa156c1ebe6a8d6587147967e8e27f6de37d99 jdk8u75-b01
@@ -538,6 +546,13 @@
 fd2b29bd7cb64a9a04d75a659bc683751b3a4f35 jdk8u75-b09
 bab68ab3df71269887bb3572291a19f7856e49dc jdk8u75-b10
 e35e96663a905f0258f6572ab6a07fbea71b9d45 jdk8u75-b12
+7bce03d47545e6a5341a2722168cd6bf697c4132 jdk8u77-b00
+678b645aa10aaf27895c87872c399c15daa026a1 jdk8u77-b01
+09abd795d1d143933224bcb3f12f5d4686b65373 jdk8u77-b02
+b6ee21a35619ce4d3b46a9b825438a3bc9bb63cd jdk8u77-b03
+a2c005a7b33abed886cfb4309a846dd80c87bd4e jdk8u91-b00
+22925b345dffe4ba96fe2f429c4185cda1b30239 jdk8u91-b13
+6296644a2c9c30db0062117fc776341e937ca1f9 jdk8u91-b14
 9ff5c21813330147bf08389b3992534780c93247 jdk8u76-b00
 b7bbed8b05dd50c27050c7e10e20d25329dcd32b jdk8u76-b01
 4c1aa7b8c43c6fd38f9c13a6df2264378dd6a873 jdk8u76-b02
@@ -550,3 +565,7 @@
 fe15575fd53e7ee8e8bf44728bab9cc0a9e6b107 jdk8u76-b09
 2816d2045f017d1b0dfd20319bbb59004d698396 jdk8u76-b10
 0608b63feb608f36bde691498d2ad22c7c24ad0f jdk8u76-b11
+da1aa86606ef1b46655ae28d34e0d02604fb4cde jdk8u76-b12
+256922f1e9e7648eb5af5a9da82ff8032b3855bc jdk8u92-b00
+e2294411edbda51165bc1a10261c246cb4d3c5c5 jdk8u92-b13
+d2af8d0297223ff16d59ee64b7058cafef8f3bb8 jdk8u92-b14