Merge
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 3c77485..11e696b 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -262,3 +262,4 @@
2a8f4c022aa03e7916223f3291517dbcc38e07cd jdk8-b132
ae6a3aec6aa29509a0fd5f53709889b99b1e27da jdk8u20-b06
6403ef94cb0db32d9221a5e8f09f3664cd7744dc jdk8u20-b07
+b7750b6ee1578fd5b2b1f6758f905b332503d8ed jdk8u20-b08
diff --git a/common/autoconf/build-aux/config.guess b/common/autoconf/build-aux/config.guess
index b0c03a7..355c91e 100644
--- a/common/autoconf/build-aux/config.guess
+++ b/common/autoconf/build-aux/config.guess
@@ -76,4 +76,14 @@
OUT=powerpc$KERNEL_BITMODE`echo $OUT | sed -e 's/[^-]*//'`
fi
+# Test and fix little endian PowerPC64.
+# TODO: should be handled by autoconf-config.guess.
+if [ "x$OUT" = x ]; then
+ if [ `uname -m` = ppc64le ]; then
+ if [ `uname -s` = Linux ]; then
+ OUT=powerpc64le-unknown-linux-gnu
+ fi
+ fi
+fi
+
echo $OUT
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index fc41d34..5ea038a 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -3868,7 +3868,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1395790635
+DATE_WHEN_GENERATED=1396481093
###############################################################################
#
@@ -6830,6 +6830,12 @@
VAR_CPU_BITS=64
VAR_CPU_ENDIAN=big
;;
+ powerpc64le)
+ VAR_CPU=ppc64
+ VAR_CPU_ARCH=ppc
+ VAR_CPU_BITS=64
+ VAR_CPU_ENDIAN=little
+ ;;
s390)
VAR_CPU=s390
VAR_CPU_ARCH=s390
@@ -6955,6 +6961,12 @@
VAR_CPU_BITS=64
VAR_CPU_ENDIAN=big
;;
+ powerpc64le)
+ VAR_CPU=ppc64
+ VAR_CPU_ARCH=ppc
+ VAR_CPU_BITS=64
+ VAR_CPU_ENDIAN=little
+ ;;
s390)
VAR_CPU=s390
VAR_CPU_ARCH=s390
diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4
index d1b1573..1f06f0c 100644
--- a/common/autoconf/platform.m4
+++ b/common/autoconf/platform.m4
@@ -60,6 +60,12 @@
VAR_CPU_BITS=64
VAR_CPU_ENDIAN=big
;;
+ powerpc64le)
+ VAR_CPU=ppc64
+ VAR_CPU_ARCH=ppc
+ VAR_CPU_BITS=64
+ VAR_CPU_ENDIAN=little
+ ;;
s390)
VAR_CPU=s390
VAR_CPU_ARCH=s390
diff --git a/corba/.hgtags b/corba/.hgtags
index 2ea6919..63fd271 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -262,3 +262,4 @@
84fed37bbe640666bfc022c2e8b9fde468de35d2 jdk8-b132
bcdc679d86aa752ccb62f6ecb182ff10ea09dce1 jdk8u20-b06
32b9c4f0ab3c6d33f70724b775cb9d12c004be6d jdk8u20-b07
+4e4a75376185ca1a712cc9fef5a340e6927cf5e2 jdk8u20-b08
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index d35f779..135a639 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -439,3 +439,5 @@
39eae002499704438142e78f5e0e24d46d0b266f hs25.20-b07
f0ea4d3df1299b6c958e1a72f892c695fca055ad jdk8u20-b07
2627c7be4279478b880d7f643a252d185e4915ec hs25.20-b08
+e9ffa408f7af28205a7114ca78bce29846f5a8df jdk8u20-b08
+5186bc5047c1725888ed99f423bdfaa116e05abe hs25.20-b09
diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version
index 265f3d1..53dcdec 100644
--- a/hotspot/make/hotspot_version
+++ b/hotspot/make/hotspot_version
@@ -35,7 +35,7 @@
HS_MAJOR_VER=25
HS_MINOR_VER=20
-HS_BUILD_NUMBER=08
+HS_BUILD_NUMBER=09
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
diff --git a/hotspot/make/linux/Makefile b/hotspot/make/linux/Makefile
index 8321f8e..df45093 100644
--- a/hotspot/make/linux/Makefile
+++ b/hotspot/make/linux/Makefile
@@ -66,8 +66,8 @@
FORCE_TIERED=1
endif
endif
-# C1 is not ported on ppc64(le), so we cannot build a tiered VM:
-ifneq (,$(filter $(ARCH),ppc64 pp64le))
+# C1 is not ported on ppc64, so we cannot build a tiered VM:
+ifeq ($(ARCH),ppc64)
FORCE_TIERED=0
endif
diff --git a/hotspot/make/linux/makefiles/defs.make b/hotspot/make/linux/makefiles/defs.make
index 377d4f9..8922fdd 100644
--- a/hotspot/make/linux/makefiles/defs.make
+++ b/hotspot/make/linux/makefiles/defs.make
@@ -33,6 +33,11 @@
# ARCH can be set explicitly in spec.gmk
ifndef ARCH
ARCH := $(shell uname -m)
+ # Fold little endian PowerPC64 into big-endian (if ARCH is set in
+ # hotspot-spec.gmk, this will be done by the configure script).
+ ifeq ($(ARCH),ppc64le)
+ ARCH := ppc64
+ endif
endif
PATH_SEP ?= :
diff --git a/hotspot/make/linux/makefiles/ppc64.make b/hotspot/make/linux/makefiles/ppc64.make
index b3e6f27..f3392de 100644
--- a/hotspot/make/linux/makefiles/ppc64.make
+++ b/hotspot/make/linux/makefiles/ppc64.make
@@ -26,14 +26,26 @@
# make c code know it is on a 64 bit platform.
CFLAGS += -D_LP64=1
-# fixes `relocation truncated to fit' error for gcc 4.1.
-CFLAGS += -mminimal-toc
+ifeq ($(origin OPENJDK_TARGET_CPU_ENDIAN),undefined)
+ # This can happen during hotspot standalone build. Set endianness from
+ # uname. We assume build and target machines are the same.
+ OPENJDK_TARGET_CPU_ENDIAN:=$(if $(filter ppc64le,$(shell uname -m)),little,big)
+endif
-# finds use ppc64 instructions, but schedule for power5
-CFLAGS += -mcpu=powerpc64 -mtune=power5 -minsert-sched-nops=regroup_exact -mno-multiple -mno-string
+ifeq ($(filter $(OPENJDK_TARGET_CPU_ENDIAN),big little),)
+ $(error OPENJDK_TARGET_CPU_ENDIAN value should be 'big' or 'little')
+endif
-# let linker find external 64 bit libs.
-LFLAGS_VM += -L/lib64
+ifeq ($(OPENJDK_TARGET_CPU_ENDIAN),big)
+ # fixes `relocation truncated to fit' error for gcc 4.1.
+ CFLAGS += -mminimal-toc
-# specify lib format.
-LFLAGS_VM += -Wl,-melf64ppc
+ # finds use ppc64 instructions, but schedule for power5
+ CFLAGS += -mcpu=powerpc64 -mtune=power5 -minsert-sched-nops=regroup_exact -mno-multiple -mno-string
+else
+ # Little endian machine uses ELFv2 ABI.
+ CFLAGS += -DVM_LITTLE_ENDIAN -DABI_ELFv2
+
+ # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI.
+ CFLAGS += -mcpu=power7 -mtune=power8 -minsert-sched-nops=regroup_exact -mno-multiple -mno-string
+endif
diff --git a/hotspot/make/windows/makefiles/defs.make b/hotspot/make/windows/makefiles/defs.make
index acf4d24..fe4b6c7 100644
--- a/hotspot/make/windows/makefiles/defs.make
+++ b/hotspot/make/windows/makefiles/defs.make
@@ -260,7 +260,6 @@
EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
endif
endif
- EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
endif
ifeq ($(JVM_VARIANT_CLIENT),true)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
@@ -275,6 +274,8 @@
endif
endif
+EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
+
ifeq ($(BUILD_WIN_SA), 1)
EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX)
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp
index 56b0b92..5a1c0f1 100644
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp
@@ -1025,15 +1025,14 @@
}
static void set_imm(int* instr, short s) {
- short* p = ((short *)instr) + 1;
- *p = s;
+ // imm is always in the lower 16 bits of the instruction,
+ // so this is endian-neutral. Same for the get_imm below.
+ uint32_t w = *(uint32_t *)instr;
+ *instr = (int)((w & ~0x0000FFFF) | (s & 0x0000FFFF));
}
static int get_imm(address a, int instruction_number) {
- short imm;
- short *p =((short *)a)+2*instruction_number+1;
- imm = *p;
- return (int)imm;
+ return (short)((int *)a)[instruction_number];
}
static inline int hi16_signed( int x) { return (int)(int16_t)(x >> 16); }
diff --git a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp
index 872aa6b..2a8fc59 100644
--- a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp
@@ -35,6 +35,126 @@
// Can I count on address always being a pointer to an unsigned char? Yes.
+#if defined(VM_LITTLE_ENDIAN)
+
+ // Returns true, if the byte ordering used by Java is different from the native byte ordering
+ // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
+ static inline bool is_Java_byte_ordering_different() { return true; }
+
+ // Forward declarations of the compiler-dependent implementation
+ static inline u2 swap_u2(u2 x);
+ static inline u4 swap_u4(u4 x);
+ static inline u8 swap_u8(u8 x);
+
+ static inline u2 get_native_u2(address p) {
+ return (intptr_t(p) & 1) == 0
+ ? *(u2*)p
+ : ( u2(p[1]) << 8 )
+ | ( u2(p[0]) );
+ }
+
+ static inline u4 get_native_u4(address p) {
+ switch (intptr_t(p) & 3) {
+ case 0: return *(u4*)p;
+
+ case 2: return ( u4( ((u2*)p)[1] ) << 16 )
+ | ( u4( ((u2*)p)[0] ) );
+
+ default: return ( u4(p[3]) << 24 )
+ | ( u4(p[2]) << 16 )
+ | ( u4(p[1]) << 8 )
+ | u4(p[0]);
+ }
+ }
+
+ static inline u8 get_native_u8(address p) {
+ switch (intptr_t(p) & 7) {
+ case 0: return *(u8*)p;
+
+ case 4: return ( u8( ((u4*)p)[1] ) << 32 )
+ | ( u8( ((u4*)p)[0] ) );
+
+ case 2: return ( u8( ((u2*)p)[3] ) << 48 )
+ | ( u8( ((u2*)p)[2] ) << 32 )
+ | ( u8( ((u2*)p)[1] ) << 16 )
+ | ( u8( ((u2*)p)[0] ) );
+
+ default: return ( u8(p[7]) << 56 )
+ | ( u8(p[6]) << 48 )
+ | ( u8(p[5]) << 40 )
+ | ( u8(p[4]) << 32 )
+ | ( u8(p[3]) << 24 )
+ | ( u8(p[2]) << 16 )
+ | ( u8(p[1]) << 8 )
+ | u8(p[0]);
+ }
+ }
+
+
+
+ static inline void put_native_u2(address p, u2 x) {
+ if ( (intptr_t(p) & 1) == 0 ) *(u2*)p = x;
+ else {
+ p[1] = x >> 8;
+ p[0] = x;
+ }
+ }
+
+ static inline void put_native_u4(address p, u4 x) {
+ switch ( intptr_t(p) & 3 ) {
+ case 0: *(u4*)p = x;
+ break;
+
+ case 2: ((u2*)p)[1] = x >> 16;
+ ((u2*)p)[0] = x;
+ break;
+
+ default: ((u1*)p)[3] = x >> 24;
+ ((u1*)p)[2] = x >> 16;
+ ((u1*)p)[1] = x >> 8;
+ ((u1*)p)[0] = x;
+ break;
+ }
+ }
+
+ static inline void put_native_u8(address p, u8 x) {
+ switch ( intptr_t(p) & 7 ) {
+ case 0: *(u8*)p = x;
+ break;
+
+ case 4: ((u4*)p)[1] = x >> 32;
+ ((u4*)p)[0] = x;
+ break;
+
+ case 2: ((u2*)p)[3] = x >> 48;
+ ((u2*)p)[2] = x >> 32;
+ ((u2*)p)[1] = x >> 16;
+ ((u2*)p)[0] = x;
+ break;
+
+ default: ((u1*)p)[7] = x >> 56;
+ ((u1*)p)[6] = x >> 48;
+ ((u1*)p)[5] = x >> 40;
+ ((u1*)p)[4] = x >> 32;
+ ((u1*)p)[3] = x >> 24;
+ ((u1*)p)[2] = x >> 16;
+ ((u1*)p)[1] = x >> 8;
+ ((u1*)p)[0] = x;
+ }
+ }
+
+ // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
+ // (no byte-order reversal is needed since Power CPUs are big-endian oriented).
+ static inline u2 get_Java_u2(address p) { return swap_u2(get_native_u2(p)); }
+ static inline u4 get_Java_u4(address p) { return swap_u4(get_native_u4(p)); }
+ static inline u8 get_Java_u8(address p) { return swap_u8(get_native_u8(p)); }
+
+ static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, swap_u2(x)); }
+ static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, swap_u4(x)); }
+ static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, swap_u8(x)); }
+
+#else // !defined(VM_LITTLE_ENDIAN)
+
// Returns true, if the byte ordering used by Java is different from the nativ byte ordering
// of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc.
static inline bool is_Java_byte_ordering_different() { return false; }
@@ -150,6 +270,12 @@
static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, x); }
static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, x); }
static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, x); }
+
+#endif // VM_LITTLE_ENDIAN
};
+#if defined(TARGET_OS_ARCH_linux_ppc)
+#include "bytes_linux_ppc.inline.hpp"
+#endif
+
#endif // CPU_PPC_VM_BYTES_PPC_HPP
diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
index bf9c934..ed1a763 100644
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
@@ -801,7 +801,13 @@
if (UseCompressedOops && !wide) {
__ movl(as_Address(addr), (int32_t)NULL_WORD);
} else {
+#ifdef _LP64
+ __ xorptr(rscratch1, rscratch1);
+ null_check_here = code_offset();
+ __ movptr(as_Address(addr), rscratch1);
+#else
__ movptr(as_Address(addr), NULL_WORD);
+#endif
}
} else {
if (is_literal_address(addr)) {
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
index 28b79b7..ba5fcb3 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
@@ -59,9 +59,9 @@
static const int stub_size = 600;
extern "C" {
- typedef void (*getPsrInfo_stub_t)(void*);
+ typedef void (*get_cpu_info_stub_t)(void*);
}
-static getPsrInfo_stub_t getPsrInfo_stub = NULL;
+static get_cpu_info_stub_t get_cpu_info_stub = NULL;
class VM_Version_StubGenerator: public StubCodeGenerator {
@@ -69,7 +69,7 @@
VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
- address generate_getPsrInfo() {
+ address generate_get_cpu_info() {
// Flags to test CPU type.
const uint32_t HS_EFL_AC = 0x40000;
const uint32_t HS_EFL_ID = 0x200000;
@@ -81,13 +81,13 @@
Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done;
- StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
+ StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub");
# define __ _masm->
address start = __ pc();
//
- // void getPsrInfo(VM_Version::CpuidInfo* cpuid_info);
+ // void get_cpu_info(VM_Version::CpuidInfo* cpuid_info);
//
// LP64: rcx and rdx are first and second argument registers on windows
@@ -385,6 +385,14 @@
};
+void VM_Version::get_cpu_info_wrapper() {
+ get_cpu_info_stub(&_cpuid_info);
+}
+
+#ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
+ #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
+#endif
+
void VM_Version::get_processor_features() {
_cpu = 4; // 486 by default
@@ -395,7 +403,11 @@
if (!Use486InstrsOnly) {
// Get raw processor info
- getPsrInfo_stub(&_cpuid_info);
+
+ // Some platforms (like Win*) need a wrapper around here
+ // in order to properly handle SEGV for YMM registers test.
+ CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(get_cpu_info_wrapper);
+
assert_is_initialized();
_cpu = extended_cpu_family();
_model = extended_cpu_model();
@@ -986,14 +998,14 @@
ResourceMark rm;
// Making this stub must be FIRST use of assembler
- stub_blob = BufferBlob::create("getPsrInfo_stub", stub_size);
+ stub_blob = BufferBlob::create("get_cpu_info_stub", stub_size);
if (stub_blob == NULL) {
- vm_exit_during_initialization("Unable to allocate getPsrInfo_stub");
+ vm_exit_during_initialization("Unable to allocate get_cpu_info_stub");
}
CodeBuffer c(stub_blob);
VM_Version_StubGenerator g(&c);
- getPsrInfo_stub = CAST_TO_FN_PTR(getPsrInfo_stub_t,
- g.generate_getPsrInfo());
+ get_cpu_info_stub = CAST_TO_FN_PTR(get_cpu_info_stub_t,
+ g.generate_get_cpu_info());
get_processor_features();
}
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
index a3be099..51f6e4f 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
@@ -507,6 +507,7 @@
// The value used to check ymm register after signal handle
static int ymm_test_value() { return 0xCAFEBABE; }
+ static void get_cpu_info_wrapper();
static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
static bool is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index 1d7437a..aa85223 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -1963,7 +1963,11 @@
{EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
{EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"},
{EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"},
+#if defined(VM_LITTLE_ENDIAN)
+ {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2LSB, (char*)"Power PC 64"},
+#else
{EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
+#endif
{EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"},
{EM_S390, EM_S390, ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"},
{EM_ALPHA, EM_ALPHA, ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"},
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index b973c32..360643c 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -2716,7 +2716,6 @@
}
#endif
-#ifndef PRODUCT
void os::win32::call_test_func_with_wrapper(void (*funcPtr)(void)) {
// Install a win32 structured exception handler around the test
// function call so the VM can generate an error dump if needed.
@@ -2727,7 +2726,6 @@
// Nothing to do.
}
}
-#endif
// Virtual Memory
diff --git a/hotspot/src/os/windows/vm/os_windows.hpp b/hotspot/src/os/windows/vm/os_windows.hpp
index c9c4840..f7c3790 100644
--- a/hotspot/src/os/windows/vm/os_windows.hpp
+++ b/hotspot/src/os/windows/vm/os_windows.hpp
@@ -97,9 +97,7 @@
static address fast_jni_accessor_wrapper(BasicType);
#endif
-#ifndef PRODUCT
static void call_test_func_with_wrapper(void (*funcPtr)(void));
-#endif
// filter function to ignore faults on serializations page
static LONG WINAPI serialize_fault_filter(struct _EXCEPTION_POINTERS* e);
diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp
index 5303743..a824b84 100644
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp
@@ -107,9 +107,7 @@
return ::close(fd);
}
-#ifndef PRODUCT
- #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \
- os::win32::call_test_func_with_wrapper(f)
-#endif
+#define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \
+ os::win32::call_test_func_with_wrapper(f)
#endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
diff --git a/hotspot/src/os_cpu/linux_ppc/vm/bytes_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/bytes_linux_ppc.inline.hpp
new file mode 100644
index 0000000..d1a9e98
--- /dev/null
+++ b/hotspot/src/os_cpu/linux_ppc/vm/bytes_linux_ppc.inline.hpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Google 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.
+ *
+ */
+
+#ifndef OS_CPU_LINUX_PPC_VM_BYTES_LINUX_PPC_INLINE_HPP
+#define OS_CPU_LINUX_PPC_VM_BYTES_LINUX_PPC_INLINE_HPP
+
+#if defined(VM_LITTLE_ENDIAN)
+#include <byteswap.h>
+
+// Efficient swapping of data bytes from Java byte
+// ordering to native byte ordering and vice versa.
+inline u2 Bytes::swap_u2(u2 x) { return bswap_16(x); }
+inline u4 Bytes::swap_u4(u4 x) { return bswap_32(x); }
+inline u8 Bytes::swap_u8(u8 x) { return bswap_64(x); }
+#endif // VM_LITTLE_ENDIAN
+
+#endif // OS_CPU_LINUX_PPC_VM_BYTES_LINUX_PPC_INLINE_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
index 7bdb98f..ddebcf5 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc_implementation/g1/dirtyCardQueue.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/heapRegionRemSet.hpp"
#include "runtime/atomic.hpp"
#include "runtime/mutexLocker.hpp"
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index c13eec9..f73eab9 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -3547,6 +3547,29 @@
}
};
+bool G1CollectedHeap::is_obj_dead_cond(const oop obj,
+ const HeapRegion* hr,
+ const VerifyOption vo) const {
+ switch (vo) {
+ case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj, hr);
+ case VerifyOption_G1UseNextMarking: return is_obj_ill(obj, hr);
+ case VerifyOption_G1UseMarkWord: return !obj->is_gc_marked();
+ default: ShouldNotReachHere();
+ }
+ return false; // keep some compilers happy
+}
+
+bool G1CollectedHeap::is_obj_dead_cond(const oop obj,
+ const VerifyOption vo) const {
+ switch (vo) {
+ case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj);
+ case VerifyOption_G1UseNextMarking: return is_obj_ill(obj);
+ case VerifyOption_G1UseMarkWord: return !obj->is_gc_marked();
+ default: ShouldNotReachHere();
+ }
+ return false; // keep some compilers happy
+}
+
void G1CollectedHeap::print_on(outputStream* st) const {
st->print(" %-20s", "garbage-first heap");
st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K",
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
index d50897d..a18436e 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
@@ -706,19 +706,7 @@
// This is a fast test on whether a reference points into the
// collection set or not. Assume that the reference
// points into the heap.
- bool in_cset_fast_test(oop obj) {
- assert(_in_cset_fast_test != NULL, "sanity");
- assert(_g1_committed.contains((HeapWord*) obj), err_msg("Given reference outside of heap, is "PTR_FORMAT, (HeapWord*)obj));
- // no need to subtract the bottom of the heap from obj,
- // _in_cset_fast_test is biased
- uintx index = cast_from_oop<uintx>(obj) >> HeapRegion::LogOfHRGrainBytes;
- bool ret = _in_cset_fast_test[index];
- // let's make sure the result is consistent with what the slower
- // test returns
- assert( ret || !obj_in_cs(obj), "sanity");
- assert(!ret || obj_in_cs(obj), "sanity");
- return ret;
- }
+ inline bool in_cset_fast_test(oop obj);
void clear_cset_fast_test() {
assert(_in_cset_fast_test_base != NULL, "sanity");
@@ -1264,9 +1252,7 @@
}
}
- void old_set_remove(HeapRegion* hr) {
- _old_set.remove(hr);
- }
+ inline void old_set_remove(HeapRegion* hr);
size_t non_young_capacity_bytes() {
return _old_set.total_capacity_bytes() + _humongous_set.total_capacity_bytes();
@@ -1357,7 +1343,7 @@
void heap_region_iterate(HeapRegionClosure* blk) const;
// Return the region with the given index. It assumes the index is valid.
- HeapRegion* region_at(uint index) const { return _hrs.at(index); }
+ inline HeapRegion* region_at(uint index) const;
// Divide the heap region sequence into "chunks" of some size (the number
// of regions divided by the number of parallel threads times some
@@ -1486,10 +1472,7 @@
return true;
}
- bool is_in_young(const oop obj) {
- HeapRegion* hr = heap_region_containing(obj);
- return hr != NULL && hr->is_young();
- }
+ inline bool is_in_young(const oop obj);
#ifdef ASSERT
virtual bool is_in_partial_collection(const void* p);
@@ -1502,9 +1485,7 @@
// pre-value that needs to be remembered; for the remembered-set
// update logging post-barrier, we don't maintain remembered set
// information for young gen objects.
- virtual bool can_elide_initializing_store_barrier(oop new_obj) {
- return is_in_young(new_obj);
- }
+ virtual inline bool can_elide_initializing_store_barrier(oop new_obj);
// Returns "true" iff the given word_size is "very large".
static bool isHumongous(size_t word_size) {
@@ -1598,23 +1579,9 @@
// Added if it is NULL it isn't dead.
- bool is_obj_dead(const oop obj) const {
- const HeapRegion* hr = heap_region_containing(obj);
- if (hr == NULL) {
- if (obj == NULL) return false;
- else return true;
- }
- else return is_obj_dead(obj, hr);
- }
+ inline bool is_obj_dead(const oop obj) const;
- bool is_obj_ill(const oop obj) const {
- const HeapRegion* hr = heap_region_containing(obj);
- if (hr == NULL) {
- if (obj == NULL) return false;
- else return true;
- }
- else return is_obj_ill(obj, hr);
- }
+ inline bool is_obj_ill(const oop obj) const;
bool allocated_since_marking(oop obj, HeapRegion* hr, VerifyOption vo);
HeapWord* top_at_mark_start(HeapRegion* hr, VerifyOption vo);
@@ -1708,26 +1675,10 @@
bool is_obj_dead_cond(const oop obj,
const HeapRegion* hr,
- const VerifyOption vo) const {
- switch (vo) {
- case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj, hr);
- case VerifyOption_G1UseNextMarking: return is_obj_ill(obj, hr);
- case VerifyOption_G1UseMarkWord: return !obj->is_gc_marked();
- default: ShouldNotReachHere();
- }
- return false; // keep some compilers happy
- }
+ const VerifyOption vo) const;
bool is_obj_dead_cond(const oop obj,
- const VerifyOption vo) const {
- switch (vo) {
- case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj);
- case VerifyOption_G1UseNextMarking: return is_obj_ill(obj);
- case VerifyOption_G1UseMarkWord: return !obj->is_gc_marked();
- default: ShouldNotReachHere();
- }
- return false; // keep some compilers happy
- }
+ const VerifyOption vo) const;
// Printing
@@ -1821,11 +1772,7 @@
DirtyCardQueue& dirty_card_queue() { return _dcq; }
G1SATBCardTableModRefBS* ctbs() { return _ct_bs; }
- template <class T> void immediate_rs_update(HeapRegion* from, T* p, int tid) {
- if (!from->is_survivor()) {
- _g1_rem->par_write_ref(from, p, tid);
- }
- }
+ template <class T> inline void immediate_rs_update(HeapRegion* from, T* p, int tid);
template <class T> void deferred_rs_update(HeapRegion* from, T* p, int tid) {
// If the new value of the field points to the same region or
@@ -1867,13 +1814,7 @@
refs()->push(ref);
}
- template <class T> void update_rs(HeapRegion* from, T* p, int tid) {
- if (G1DeferredRSUpdate) {
- deferred_rs_update(from, p, tid);
- } else {
- immediate_rs_update(from, p, tid);
- }
- }
+ template <class T> inline void update_rs(HeapRegion* from, T* p, int tid);
HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
HeapWord* obj = NULL;
@@ -1997,54 +1938,7 @@
return cast_to_oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK);
}
- void do_oop_partial_array(oop* p) {
- assert(has_partial_array_mask(p), "invariant");
- oop from_obj = clear_partial_array_mask(p);
-
- assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap.");
- assert(from_obj->is_objArray(), "must be obj array");
- objArrayOop from_obj_array = objArrayOop(from_obj);
- // The from-space object contains the real length.
- int length = from_obj_array->length();
-
- assert(from_obj->is_forwarded(), "must be forwarded");
- oop to_obj = from_obj->forwardee();
- assert(from_obj != to_obj, "should not be chunking self-forwarded objects");
- objArrayOop to_obj_array = objArrayOop(to_obj);
- // We keep track of the next start index in the length field of the
- // to-space object.
- int next_index = to_obj_array->length();
- assert(0 <= next_index && next_index < length,
- err_msg("invariant, next index: %d, length: %d", next_index, length));
-
- int start = next_index;
- int end = length;
- int remainder = end - start;
- // We'll try not to push a range that's smaller than ParGCArrayScanChunk.
- if (remainder > 2 * ParGCArrayScanChunk) {
- end = start + ParGCArrayScanChunk;
- to_obj_array->set_length(end);
- // Push the remainder before we process the range in case another
- // worker has run out of things to do and can steal it.
- oop* from_obj_p = set_partial_array_mask(from_obj);
- push_on_queue(from_obj_p);
- } else {
- assert(length == end, "sanity");
- // We'll process the final range for this object. Restore the length
- // so that the heap remains parsable in case of evacuation failure.
- to_obj_array->set_length(end);
- }
- _scanner.set_region(_g1h->heap_region_containing_raw(to_obj));
- // Process indexes [start,end). It will also process the header
- // along with the first chunk (i.e., the chunk with start == 0).
- // Note that at this point the length field of to_obj_array is not
- // correct given that we are using it to keep track of the next
- // start index. oop_iterate_range() (thankfully!) ignores the length
- // field and only relies on the start / end parameters. It does
- // however return the size of the object which will be incorrect. So
- // we have to ignore it even if we wanted to use it.
- to_obj_array->oop_iterate_range(&_scanner, start, end);
- }
+ inline void do_oop_partial_array(oop* p);
// This method is applied to the fields of the objects that have just been copied.
template <class T> void do_oop_evac(T* p, HeapRegion* from) {
@@ -2074,26 +1968,9 @@
oop copy_to_survivor_space(oop const obj);
- template <class T> void deal_with_reference(T* ref_to_scan) {
- if (!has_partial_array_mask(ref_to_scan)) {
- // Note: we can use "raw" versions of "region_containing" because
- // "obj_to_scan" is definitely in the heap, and is not in a
- // humongous region.
- HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan);
- do_oop_evac(ref_to_scan, r);
- } else {
- do_oop_partial_array((oop*)ref_to_scan);
- }
- }
+ template <class T> inline void deal_with_reference(T* ref_to_scan);
- void deal_with_reference(StarTask ref) {
- assert(verify_task(ref), "sanity");
- if (ref.is_narrow()) {
- deal_with_reference((narrowOop*)ref);
- } else {
- deal_with_reference((oop*)ref);
- }
- }
+ inline void deal_with_reference(StarTask ref);
public:
void trim_queue();
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp
index 91289d6..e3b8fd0 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp
@@ -29,6 +29,7 @@
#include "gc_implementation/g1/g1CollectedHeap.hpp"
#include "gc_implementation/g1/g1AllocRegion.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
+#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#include "gc_implementation/g1/heapRegionSet.inline.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
@@ -36,6 +37,9 @@
// Inline functions for G1CollectedHeap
+// Return the region with the given index. It assumes the index is valid.
+inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrs.at(index); }
+
template <class T>
inline HeapRegion*
G1CollectedHeap::heap_region_containing(const T addr) const {
@@ -55,6 +59,10 @@
return res;
}
+inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) {
+ _old_set.remove(hr);
+}
+
inline bool G1CollectedHeap::obj_in_cs(oop obj) {
HeapRegion* r = _hrs.addr_to_region((HeapWord*) obj);
return r != NULL && r->in_collection_set();
@@ -151,6 +159,24 @@
return _cm->nextMarkBitMap()->isMarked((HeapWord *)obj);
}
+
+// This is a fast test on whether a reference points into the
+// collection set or not. Assume that the reference
+// points into the heap.
+inline bool G1CollectedHeap::in_cset_fast_test(oop obj) {
+ assert(_in_cset_fast_test != NULL, "sanity");
+ assert(_g1_committed.contains((HeapWord*) obj), err_msg("Given reference outside of heap, is "PTR_FORMAT, (HeapWord*)obj));
+ // no need to subtract the bottom of the heap from obj,
+ // _in_cset_fast_test is biased
+ uintx index = cast_from_oop<uintx>(obj) >> HeapRegion::LogOfHRGrainBytes;
+ bool ret = _in_cset_fast_test[index];
+ // let's make sure the result is consistent with what the slower
+ // test returns
+ assert( ret || !obj_in_cs(obj), "sanity");
+ assert(!ret || obj_in_cs(obj), "sanity");
+ return ret;
+}
+
#ifndef PRODUCT
// Support for G1EvacuationFailureALot
@@ -224,4 +250,121 @@
}
#endif // #ifndef PRODUCT
+inline bool G1CollectedHeap::is_in_young(const oop obj) {
+ HeapRegion* hr = heap_region_containing(obj);
+ return hr != NULL && hr->is_young();
+}
+
+// We don't need barriers for initializing stores to objects
+// in the young gen: for the SATB pre-barrier, there is no
+// pre-value that needs to be remembered; for the remembered-set
+// update logging post-barrier, we don't maintain remembered set
+// information for young gen objects.
+inline bool G1CollectedHeap::can_elide_initializing_store_barrier(oop new_obj) {
+ return is_in_young(new_obj);
+}
+
+inline bool G1CollectedHeap::is_obj_dead(const oop obj) const {
+ const HeapRegion* hr = heap_region_containing(obj);
+ if (hr == NULL) {
+ if (obj == NULL) return false;
+ else return true;
+ }
+ else return is_obj_dead(obj, hr);
+}
+
+inline bool G1CollectedHeap::is_obj_ill(const oop obj) const {
+ const HeapRegion* hr = heap_region_containing(obj);
+ if (hr == NULL) {
+ if (obj == NULL) return false;
+ else return true;
+ }
+ else return is_obj_ill(obj, hr);
+}
+
+template <class T> inline void G1ParScanThreadState::immediate_rs_update(HeapRegion* from, T* p, int tid) {
+ if (!from->is_survivor()) {
+ _g1_rem->par_write_ref(from, p, tid);
+ }
+}
+
+template <class T> void G1ParScanThreadState::update_rs(HeapRegion* from, T* p, int tid) {
+ if (G1DeferredRSUpdate) {
+ deferred_rs_update(from, p, tid);
+ } else {
+ immediate_rs_update(from, p, tid);
+ }
+}
+
+
+inline void G1ParScanThreadState::do_oop_partial_array(oop* p) {
+ assert(has_partial_array_mask(p), "invariant");
+ oop from_obj = clear_partial_array_mask(p);
+
+ assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap.");
+ assert(from_obj->is_objArray(), "must be obj array");
+ objArrayOop from_obj_array = objArrayOop(from_obj);
+ // The from-space object contains the real length.
+ int length = from_obj_array->length();
+
+ assert(from_obj->is_forwarded(), "must be forwarded");
+ oop to_obj = from_obj->forwardee();
+ assert(from_obj != to_obj, "should not be chunking self-forwarded objects");
+ objArrayOop to_obj_array = objArrayOop(to_obj);
+ // We keep track of the next start index in the length field of the
+ // to-space object.
+ int next_index = to_obj_array->length();
+ assert(0 <= next_index && next_index < length,
+ err_msg("invariant, next index: %d, length: %d", next_index, length));
+
+ int start = next_index;
+ int end = length;
+ int remainder = end - start;
+ // We'll try not to push a range that's smaller than ParGCArrayScanChunk.
+ if (remainder > 2 * ParGCArrayScanChunk) {
+ end = start + ParGCArrayScanChunk;
+ to_obj_array->set_length(end);
+ // Push the remainder before we process the range in case another
+ // worker has run out of things to do and can steal it.
+ oop* from_obj_p = set_partial_array_mask(from_obj);
+ push_on_queue(from_obj_p);
+ } else {
+ assert(length == end, "sanity");
+ // We'll process the final range for this object. Restore the length
+ // so that the heap remains parsable in case of evacuation failure.
+ to_obj_array->set_length(end);
+ }
+ _scanner.set_region(_g1h->heap_region_containing_raw(to_obj));
+ // Process indexes [start,end). It will also process the header
+ // along with the first chunk (i.e., the chunk with start == 0).
+ // Note that at this point the length field of to_obj_array is not
+ // correct given that we are using it to keep track of the next
+ // start index. oop_iterate_range() (thankfully!) ignores the length
+ // field and only relies on the start / end parameters. It does
+ // however return the size of the object which will be incorrect. So
+ // we have to ignore it even if we wanted to use it.
+ to_obj_array->oop_iterate_range(&_scanner, start, end);
+}
+
+template <class T> inline void G1ParScanThreadState::deal_with_reference(T* ref_to_scan) {
+ if (!has_partial_array_mask(ref_to_scan)) {
+ // Note: we can use "raw" versions of "region_containing" because
+ // "obj_to_scan" is definitely in the heap, and is not in a
+ // humongous region.
+ HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan);
+ do_oop_evac(ref_to_scan, r);
+ } else {
+ do_oop_partial_array((oop*)ref_to_scan);
+ }
+}
+
+inline void G1ParScanThreadState::deal_with_reference(StarTask ref) {
+ assert(verify_task(ref), "sanity");
+ if (ref.is_narrow()) {
+ deal_with_reference((narrowOop*)ref);
+ } else {
+ deal_with_reference((oop*)ref);
+ }
+}
+
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_INLINE_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp
index 86d5db1..5cc8846 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp
@@ -25,7 +25,7 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP
-#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.hpp"
#include "gc_implementation/g1/heapRegion.hpp"
#include "memory/allocation.hpp"
#include "memory/cardTableModRefBS.hpp"
diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp
index 6ee1510..eb7de64 100644
--- a/hotspot/src/share/vm/prims/jni.cpp
+++ b/hotspot/src/share/vm/prims/jni.cpp
@@ -5208,7 +5208,7 @@
}
#ifndef PRODUCT
- #ifndef TARGET_OS_FAMILY_windows
+ #ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
#define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
#endif
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 9f28fc2..7441f26 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -1880,24 +1880,22 @@
// check if do gclog rotation
// +UseGCLogFileRotation is a must,
// no gc log rotation when log file not supplied or
-// NumberOfGCLogFiles is 0, or GCLogFileSize is 0
+// NumberOfGCLogFiles is 0
void check_gclog_consistency() {
if (UseGCLogFileRotation) {
- if ((Arguments::gc_log_filename() == NULL) ||
- (NumberOfGCLogFiles == 0) ||
- (GCLogFileSize == 0)) {
+ if ((Arguments::gc_log_filename() == NULL) || (NumberOfGCLogFiles == 0)) {
jio_fprintf(defaultStream::output_stream(),
- "To enable GC log rotation, use -Xloggc:<filename> -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<num_of_files> -XX:GCLogFileSize=<num_of_size>[k|K|m|M|g|G]\n"
- "where num_of_file > 0 and num_of_size > 0\n"
+ "To enable GC log rotation, use -Xloggc:<filename> -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<num_of_files>\n"
+ "where num_of_file > 0\n"
"GC log rotation is turned off\n");
UseGCLogFileRotation = false;
}
}
- if (UseGCLogFileRotation && GCLogFileSize < 8*K) {
- FLAG_SET_CMDLINE(uintx, GCLogFileSize, 8*K);
- jio_fprintf(defaultStream::output_stream(),
- "GCLogFileSize changed to minimum 8K\n");
+ if (UseGCLogFileRotation && (GCLogFileSize != 0) && (GCLogFileSize < 8*K)) {
+ FLAG_SET_CMDLINE(uintx, GCLogFileSize, 8*K);
+ jio_fprintf(defaultStream::output_stream(),
+ "GCLogFileSize changed to minimum 8K\n");
}
}
diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp
index 74f7acd..801f7b8 100644
--- a/hotspot/src/share/vm/runtime/globals.cpp
+++ b/hotspot/src/share/vm/runtime/globals.cpp
@@ -325,7 +325,7 @@
else st->print("%-16s", "");
}
- st->print("%-20");
+ st->print("%-20s", " ");
print_kind(st);
if (withComments) {
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index ff05111..9927eb7 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -2422,9 +2422,9 @@
"Number of gclog files in rotation " \
"(default: 0, no rotation)") \
\
- product(uintx, GCLogFileSize, 0, \
- "GC log file size (default: 0 bytes, no rotation). " \
- "It requires UseGCLogFileRotation") \
+ product(uintx, GCLogFileSize, 8*K, \
+ "GC log file size, requires UseGCLogFileRotation. " \
+ "Set to 0 to only trigger rotation via jcmd") \
\
/* JVMTI heap profiling */ \
\
diff --git a/hotspot/src/share/vm/runtime/safepoint.cpp b/hotspot/src/share/vm/runtime/safepoint.cpp
index 48e523f..cac23e9 100644
--- a/hotspot/src/share/vm/runtime/safepoint.cpp
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp
@@ -535,7 +535,7 @@
// rotate log files?
if (UseGCLogFileRotation) {
- gclog_or_tty->rotate_log();
+ gclog_or_tty->rotate_log(false);
}
if (MemTracker::is_on()) {
diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp
index ca616a5..0cb3a18 100644
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp
@@ -94,6 +94,7 @@
template(JFRCheckpoint) \
template(Exit) \
template(LinuxDllLoad) \
+ template(RotateGCLog) \
class VM_Operation: public CHeapObj<mtInternal> {
public:
@@ -397,4 +398,15 @@
void doit();
};
+
+class VM_RotateGCLog: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_RotateGCLog(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_RotateGCLog; }
+ void doit() { gclog_or_tty->rotate_log(true, _out); }
+};
+
#endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP
diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp
index 71b5528..1245b5a 100644
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp
@@ -53,6 +53,7 @@
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(full_export, true, false));
#endif // INCLUDE_SERVICES
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false));
// Enhanced JMX Agent Support
// These commands won't be exported via the DiagnosticCommandMBean until an
@@ -650,3 +651,11 @@
JavaCalls::call_static(&result, ik, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);
}
+void RotateGCLogDCmd::execute(DCmdSource source, TRAPS) {
+ if (UseGCLogFileRotation) {
+ VM_RotateGCLog rotateop(output());
+ VMThread::execute(&rotateop);
+ } else {
+ output()->print_cr("Target VM does not support GC log file rotation.");
+ }
+}
diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp
index 5485b11..2ce4109 100644
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp
@@ -360,4 +360,21 @@
virtual void execute(DCmdSource source, TRAPS);
};
+class RotateGCLogDCmd : public DCmd {
+public:
+ RotateGCLogDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() { return "GC.rotate_log"; }
+ static const char* description() {
+ return "Force the GC log file to be rotated.";
+ }
+ static const char* impact() { return "Low"; }
+ virtual void execute(DCmdSource source, TRAPS);
+ static int num_arguments() { return 0; }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "control", NULL};
+ return p;
+ }
+};
+
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp
index 90b3559..e09dfcc 100644
--- a/hotspot/src/share/vm/utilities/ostream.cpp
+++ b/hotspot/src/share/vm/utilities/ostream.cpp
@@ -662,13 +662,13 @@
// write to gc log file at safepoint. If in future, changes made for mutator threads or
// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
// must be synchronized.
-void gcLogFileStream::rotate_log() {
+void gcLogFileStream::rotate_log(bool force, outputStream* out) {
char time_msg[FILENAMEBUFLEN];
char time_str[EXTRACHARLEN];
char current_file_name[FILENAMEBUFLEN];
char renamed_file_name[FILENAMEBUFLEN];
- if (_bytes_written < (jlong)GCLogFileSize) {
+ if (!should_rotate(force)) {
return;
}
@@ -685,6 +685,11 @@
jio_snprintf(time_msg, sizeof(time_msg), "File %s rotated at %s\n",
_file_name, os::local_time_string((char *)time_str, sizeof(time_str)));
write(time_msg, strlen(time_msg));
+
+ if (out != NULL) {
+ out->print(time_msg);
+ }
+
dump_loggc_header();
return;
}
@@ -706,12 +711,18 @@
_file_name, _cur_file_num);
jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
_file_name, _cur_file_num);
- jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file has reached the"
- " maximum size. Saved as %s\n",
- os::local_time_string((char *)time_str, sizeof(time_str)),
- renamed_file_name);
+
+ const char* msg = force ? "GC log rotation request has been received."
+ : "GC log file has reached the maximum size.";
+ jio_snprintf(time_msg, sizeof(time_msg), "%s %s Saved as %s\n",
+ os::local_time_string((char *)time_str, sizeof(time_str)),
+ msg, renamed_file_name);
write(time_msg, strlen(time_msg));
+ if (out != NULL) {
+ out->print(time_msg);
+ }
+
fclose(_file);
_file = NULL;
@@ -752,6 +763,11 @@
os::local_time_string((char *)time_str, sizeof(time_str)),
current_file_name);
write(time_msg, strlen(time_msg));
+
+ if (out != NULL) {
+ out->print(time_msg);
+ }
+
dump_loggc_header();
// remove the existing file
if (access(current_file_name, F_OK) == 0) {
diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp
index 20e6f30..b783787 100644
--- a/hotspot/src/share/vm/utilities/ostream.hpp
+++ b/hotspot/src/share/vm/utilities/ostream.hpp
@@ -115,7 +115,7 @@
// flushing
virtual void flush() {}
virtual void write(const char* str, size_t len) = 0;
- virtual void rotate_log() {} // GC log rotation
+ virtual void rotate_log(bool force, outputStream* out = NULL) {} // GC log rotation
virtual ~outputStream() {} // close properly on deletion
void dec_cr() { dec(); cr(); }
@@ -240,8 +240,15 @@
gcLogFileStream(const char* file_name);
~gcLogFileStream();
virtual void write(const char* c, size_t len);
- virtual void rotate_log();
+ virtual void rotate_log(bool force, outputStream* out = NULL);
void dump_loggc_header();
+
+ /* If "force" sets true, force log file rotation from outside JVM */
+ bool should_rotate(bool force) {
+ return force ||
+ ((GCLogFileSize != 0) && ((uintx)_bytes_written >= GCLogFileSize));
+ }
+
};
#ifndef PRODUCT
diff --git a/hotspot/test/compiler/codegen/C1NullCheckOfNullStore.java b/hotspot/test/compiler/codegen/C1NullCheckOfNullStore.java
new file mode 100644
index 0000000..0bec2c1
--- /dev/null
+++ b/hotspot/test/compiler/codegen/C1NullCheckOfNullStore.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, 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 8039043
+ * @summary Null check is placed in a wrong place when storing a null to an object field on x64 with compressed oops off
+ * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CompileCommand=compileonly,C1NullCheckOfNullStore::test -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-UseCompressedOops C1NullCheckOfNullStore
+ *
+ */
+
+public class C1NullCheckOfNullStore {
+ private static class Foo {
+ Object bar;
+ }
+ static private void test(Foo x) {
+ x.bar = null;
+ }
+ static public void main(String args[]) {
+ Foo x = new Foo();
+ for (int i = 0; i < 10000; i++) {
+ test(x);
+ }
+ boolean gotNPE = false;
+ try {
+ for (int i = 0; i < 10000; i++) {
+ test(null);
+ }
+ }
+ catch(NullPointerException e) {
+ gotNPE = true;
+ }
+ if (!gotNPE) {
+ throw new Error("Expecting a NullPointerException");
+ }
+ }
+}
diff --git a/hotspot/test/gc/TestGCLogRotationViaJcmd.java b/hotspot/test/gc/TestGCLogRotationViaJcmd.java
new file mode 100644
index 0000000..fd71d36
--- /dev/null
+++ b/hotspot/test/gc/TestGCLogRotationViaJcmd.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, 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 TestGCLogRotationViaJcmd.java
+ * @bug 7090324
+ * @summary test for gc log rotation via jcmd
+ * @library /testlibrary
+ * @run main/othervm -Xloggc:test.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=3 TestGCLogRotationViaJcmd
+ *
+ */
+import com.oracle.java.testlibrary.*;
+import java.io.File;
+import java.io.FilenameFilter;
+
+public class TestGCLogRotationViaJcmd {
+
+ static final File currentDirectory = new File(".");
+ static final String LOG_FILE_NAME = "test.log";
+ static final int NUM_LOGS = 3;
+
+ static FilenameFilter logFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith(LOG_FILE_NAME);
+ }
+ };
+
+ public static void main(String[] args) throws Exception {
+ // Grab the pid from the current java process
+ String pid = Integer.toString(ProcessTools.getProcessId());
+
+ // Create a JDKToolLauncher
+ JDKToolLauncher jcmd = JDKToolLauncher.create("jcmd")
+ .addToolArg(pid)
+ .addToolArg("GC.rotate_log");
+
+ for (int times = 1; times < NUM_LOGS; times++) {
+ // Run jcmd <pid> GC.rotate_log
+ ProcessBuilder pb = new ProcessBuilder(jcmd.getCommand());
+
+ // Make sure we didn't crash
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ }
+
+ // GC log check
+ File[] logs = currentDirectory.listFiles(logFilter);
+ if (logs.length != NUM_LOGS) {
+ throw new Error("There are only " + logs.length
+ + " logs instead " + NUM_LOGS);
+ }
+
+ }
+
+}
+
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index f384992..f4dd8bb 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -262,3 +262,4 @@
5993346020d14a1c2c7003588c584366db7921f5 jdk8-b132
7b1a6da8ad82b8f576f21ae0692e825395f8b31b jdk8u20-b06
30b8baceb72bcec111c6aad37eef96d18c09e4ef jdk8u20-b07
+68e2ea32f92731b8ad8157252116db89903b51a3 jdk8u20-b08
diff --git a/jaxp/test/javax/xml/jaxp/parsers/8032909/XSLT.java b/jaxp/test/javax/xml/jaxp/parsers/8032909/XSLT.java
deleted file mode 100644
index d133920..0000000
--- a/jaxp/test/javax/xml/jaxp/parsers/8032909/XSLT.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, 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 8032909
- * @summary Test for XSLT string-length function with complementary chars
- * @compile XSLT.java
- * @run main/othervm XSLT a_utf16.xml a_utf16.xsl 1270
- * @run main/othervm XSLT a_utf8.xml a_utf8.xsl 130
- * @run main/othervm XSLT a_windows1252.xml a_windows1252.xsl 200
- */
-
-import java.io.ByteArrayOutputStream;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-
-public class XSLT {
- public static void main(String[] args) throws Exception {
-
- ByteArrayOutputStream resStream = new ByteArrayOutputStream();
- TransformerFactory trf = TransformerFactory.newInstance();
- Transformer tr = trf.newTransformer(new StreamSource(System.getProperty("test.src", ".")+"/"+args[1]));
- String res, expectedRes;
- tr.transform( new StreamSource(System.getProperty("test.src", ".")+"/"+args[0]), new StreamResult(resStream));
- res = resStream.toString();
- System.out.println("Transformation completed. Result:"+res);
-
- if (!res.replaceAll("\\s","").equals(args[2]))
- throw new RuntimeException("Incorrect transformation result. Expected:"+args[2]+" Observed:"+res);
- }
-}
diff --git a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf16.xml b/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf16.xml
deleted file mode 100644
index fae65cc..0000000
--- a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf16.xml
+++ /dev/null
Binary files differ
diff --git a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf16.xsl b/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf16.xsl
deleted file mode 100644
index 4d88603..0000000
--- a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf16.xsl
+++ /dev/null
Binary files differ
diff --git a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf8.xml b/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf8.xml
deleted file mode 100644
index a3b327f..0000000
--- a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf8.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<testxml>
-<Element>UTF-8_Element</Element>
-<Element2></Element2>
-</testxml>
diff --git a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf8.xsl b/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf8.xsl
deleted file mode 100644
index b7e222b..0000000
--- a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_utf8.xsl
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-
-<xsl:output method="text" />
-
-<xsl:template match="Element">
-<xsl:value-of select="string-length(.)"/>
-</xsl:template>
-<xsl:template match="Element2">
-<xsl:value-of select="string-length(.)"/>
-</xsl:template>
-
-</xsl:stylesheet>
diff --git a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_windows1252.xml b/jaxp/test/javax/xml/jaxp/parsers/8032909/a_windows1252.xml
deleted file mode 100644
index 6d5726e..0000000
--- a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_windows1252.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="windows-1252"?>
-<testxml>
-<Element>Windows-1252_Element</Element>
-<Element2></Element2>
-</testxml>
diff --git a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_windows1252.xsl b/jaxp/test/javax/xml/jaxp/parsers/8032909/a_windows1252.xsl
deleted file mode 100644
index ff50bf8..0000000
--- a/jaxp/test/javax/xml/jaxp/parsers/8032909/a_windows1252.xsl
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="windows-1252"?>
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-
-<xsl:output method="text" />
-
-<xsl:template match="Element">
-<xsl:value-of select="string-length(.)"/>
-</xsl:template>
-<xsl:template match="Element2">
-<xsl:value-of select="string-length(.)"/>
-</xsl:template>
-
-</xsl:stylesheet>
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index b239046..0e0335a 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -262,3 +262,4 @@
c2be0dd15dbf0c23ee693a1af32f8f6a012abd1e jdk8-b132
515ddaddbb6402452f5c6a63594db5d7d71b5aa1 jdk8u20-b06
a61ba2e3e6c85f7067fb7b0c3c02584abdfa96be jdk8u20-b07
+bc6d2f3426f3d04adc8245ad120e2b52fe7dfbde jdk8u20-b08
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 9c2d157..6e33fea 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -262,3 +262,4 @@
43cb25339b5500871f41388a5197f1b01c4b57b8 jdk8-b132
1ecfc0fac3e7b931f09728b7594384ea5b5f9f0f jdk8u20-b06
db30cb9eb18dacea39c35daf15a3ee5fea41fd86 jdk8u20-b07
+0e717bd55bc9e3f3fa3432e545944d81ed887ab0 jdk8u20-b08
diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaIcon.java b/jdk/src/macosx/classes/com/apple/laf/AquaIcon.java
index 576661b..e40d066 100644
--- a/jdk/src/macosx/classes/com/apple/laf/AquaIcon.java
+++ b/jdk/src/macosx/classes/com/apple/laf/AquaIcon.java
@@ -295,14 +295,8 @@
}
Image createImage() {
- int w = getIconWidth();
- int h = getIconHeight();
- return new AquaImageFactory.MultiResolutionIconImage(
- AquaUtils.getCImageCreator().createSystemImageFromSelector(
- selector, w, h),
- AquaUtils.getCImageCreator().createSystemImageFromSelector(
- selector, 2 * w, 2 * h)
- );
+ return AquaUtils.getCImageCreator().createSystemImageFromSelector(
+ selector, getIconWidth(), getIconHeight());
}
}
}
diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaImageFactory.java b/jdk/src/macosx/classes/com/apple/laf/AquaImageFactory.java
index 5451abd..0f4d0b5 100644
--- a/jdk/src/macosx/classes/com/apple/laf/AquaImageFactory.java
+++ b/jdk/src/macosx/classes/com/apple/laf/AquaImageFactory.java
@@ -125,16 +125,14 @@
private static final int kAlertIconSize = 64;
static IconUIResource getAppIconCompositedOn(final Image background) {
- final BufferedImage iconImage = getAppIconImageCompositedOn(background, 1);
-
- if (background instanceof MultiResolutionIconImage) {
- BufferedImage background2x
- = ((MultiResolutionIconImage) background).resolutionVariant;
- BufferedImage icon2xImage = getAppIconImageCompositedOn(background2x, 2);
-
- return new IconUIResource(new ImageIcon(
- new MultiResolutionIconImage(iconImage, icon2xImage)));
+ if (background instanceof MultiResolutionBufferedImage) {
+ int width = background.getWidth(null);
+ Image mrIconImage = ((MultiResolutionBufferedImage) background).map(
+ rv -> getAppIconImageCompositedOn(rv, rv.getWidth(null) / width));
+ return new IconUIResource(new ImageIcon(mrIconImage));
}
+
+ BufferedImage iconImage = getAppIconImageCompositedOn(background, 1);
return new IconUIResource(new ImageIcon(iconImage));
}
@@ -312,10 +310,16 @@
return icon;
}
- Image icon2x = AquaUtils.getCImageCreator().createImageFromName(
- imageName, 2 * icon.getWidth(null), 2 * icon.getHeight(null));
- return new MultiResolutionBufferedImage(
- BufferedImage.TYPE_INT_ARGB_PRE, 0, icon, icon2x);
+ int w = icon.getWidth(null);
+ int h = icon.getHeight(null);
+
+ Dimension[] sizes = new Dimension[]{
+ new Dimension(w, h), new Dimension(2 * w, 2 * h)
+ };
+
+ return new MultiResolutionBufferedImage(icon, sizes, (width, height) ->
+ AquaUtils.getCImageCreator().createImageFromName(
+ imageName, width, height));
}
public static class NineSliceMetrics {
@@ -524,29 +528,4 @@
public static Color getSelectionInactiveForegroundColorUIResource() {
return new SystemColorProxy(LWCToolkit.getAppleColor(LWCToolkit.INACTIVE_SELECTION_FOREGROUND_COLOR));
}
-
- static class MultiResolutionIconImage extends BufferedImage
- implements MultiResolutionImage {
-
- BufferedImage resolutionVariant;
-
- public MultiResolutionIconImage(BufferedImage image, BufferedImage resolutionVariant) {
- super(image.getWidth(), image.getHeight(), image.getType());
- this.resolutionVariant = resolutionVariant;
- Graphics g = getGraphics();
- g.drawImage(image, 0, 0, null);
- g.dispose();
- }
-
- @Override
- public Image getResolutionVariant(int width, int height) {
- return ((width <= getWidth() && height <= getHeight()))
- ? this : resolutionVariant;
- }
-
- @Override
- public List<Image> getResolutionVariants() {
- return Arrays.asList(this, resolutionVariant);
- }
- }
-}
+}
\ No newline at end of file
diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaPainter.java b/jdk/src/macosx/classes/com/apple/laf/AquaPainter.java
index dc34b69..38884ac 100644
--- a/jdk/src/macosx/classes/com/apple/laf/AquaPainter.java
+++ b/jdk/src/macosx/classes/com/apple/laf/AquaPainter.java
@@ -38,6 +38,7 @@
import sun.print.*;
import apple.laf.*;
import apple.laf.JRSUIUtils.NineSliceMetricsProvider;
+import sun.awt.image.ImageCache;
abstract class AquaPainter <T extends JRSUIState> {
static <T extends JRSUIState> AquaPainter<T> create(final T state) {
@@ -155,10 +156,15 @@
final ImageCache cache = ImageCache.getInstance();
final int imgW = bounds.width * scale;
final int imgH = bounds.height * scale;
- BufferedImage img = (BufferedImage) cache.getImage(config, imgW, imgH, scale, controlState);
+ AquaPixelsKey key = new AquaPixelsKey(config,
+ imgW, imgH, scale, controlState);
+ BufferedImage img = (BufferedImage) cache.getImage(key);
if (img == null) {
img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB_PRE);
- cache.setImage(img, config, imgW, imgH, scale, controlState);
+ if (!controlState.is(JRSUIConstants.Animating.YES)) {
+ cache.setImage(key, img);
+ }
+
final WritableRaster raster = img.getRaster();
final DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer();
@@ -172,6 +178,59 @@
}
}
+ private static class AquaPixelsKey implements ImageCache.PixelsKey {
+
+ private final int pixelCount;
+ private final int hash;
+
+ // key parts
+ private final GraphicsConfiguration config;
+ private final int w;
+ private final int h;
+ private final int scale;
+ private final JRSUIState state;
+
+ AquaPixelsKey(final GraphicsConfiguration config,
+ final int w, final int h, final int scale,
+ final JRSUIState state) {
+ this.pixelCount = w * h;
+ this.config = config;
+ this.w = w;
+ this.h = h;
+ this.scale = scale;
+ this.state = state;
+ this.hash = hash();
+ }
+
+ public int getPixelCount() {
+ return pixelCount;
+ }
+
+ private int hash() {
+ int hash = config != null ? config.hashCode() : 0;
+ hash = 31 * hash + w;
+ hash = 31 * hash + h;
+ hash = 31 * hash + scale;
+ hash = 31 * hash + state.hashCode();
+ return hash;
+ }
+
+ @Override
+ public int hashCode() {
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof AquaPixelsKey) {
+ AquaPixelsKey key = (AquaPixelsKey) obj;
+ return config == key.config && w == key.w && h == key.h
+ && scale == key.scale && state.equals(key.state);
+ }
+ return false;
+ }
+ }
+
private static class RecyclableJRSUISlicedImageControl
extends RecyclableSlicedImageControl {
diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaUtils.java b/jdk/src/macosx/classes/com/apple/laf/AquaUtils.java
index 6a52283..a20897f 100644
--- a/jdk/src/macosx/classes/com/apple/laf/AquaUtils.java
+++ b/jdk/src/macosx/classes/com/apple/laf/AquaUtils.java
@@ -177,16 +177,7 @@
abstract static class RecyclableSingleton<T> {
final T get() {
- final AppContext appContext = AppContext.getAppContext();
- SoftReference<T> ref = (SoftReference<T>) appContext.get(this);
- if (ref != null) {
- final T object = ref.get();
- if (object != null) return object;
- }
- final T object = getInstance();
- ref = new SoftReference<T>(object);
- appContext.put(this, ref);
- return object;
+ return AppContext.getSoftReferenceValue(this, () -> getInstance());
}
void reset() {
diff --git a/jdk/src/macosx/classes/com/apple/laf/ImageCache.java b/jdk/src/macosx/classes/com/apple/laf/ImageCache.java
deleted file mode 100644
index 442b974..0000000
--- a/jdk/src/macosx/classes/com/apple/laf/ImageCache.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2011, 2013, 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 com.apple.laf;
-
-import java.awt.*;
-import java.lang.ref.*;
-import java.util.*;
-import java.util.concurrent.locks.*;
-
-import apple.laf.JRSUIConstants;
-import apple.laf.JRSUIState;
-import com.apple.laf.AquaUtils.RecyclableSingleton;
-
-/**
- * ImageCache - A fixed pixel count sized cache of Images keyed by arbitrary set of arguments. All images are held with
- * SoftReferences so they will be dropped by the GC if heap memory gets tight. When our size hits max pixel count least
- * recently requested images are removed first.
- */
-final class ImageCache {
- // Ordered Map keyed by args hash, ordered by most recent accessed entry.
- private final LinkedHashMap<Integer, PixelCountSoftReference> map = new LinkedHashMap<>(16, 0.75f, true);
-
- // Maximum number of pixels to cache, this is used if maxCount
- private final int maxPixelCount;
- // The current number of pixels stored in the cache
- private int currentPixelCount = 0;
-
- // Lock for concurrent access to map
- private final ReadWriteLock lock = new ReentrantReadWriteLock();
- // Reference queue for tracking lost softreferences to images in the cache
- private final ReferenceQueue<Image> referenceQueue = new ReferenceQueue<>();
-
- // Singleton Instance
- private static final RecyclableSingleton<ImageCache> instance = new RecyclableSingleton<ImageCache>() {
- @Override
- protected ImageCache getInstance() {
- return new ImageCache();
- }
- };
- static ImageCache getInstance() {
- return instance.get();
- }
-
- ImageCache(final int maxPixelCount) {
- this.maxPixelCount = maxPixelCount;
- }
-
- ImageCache() {
- this((8 * 1024 * 1024) / 4); // 8Mb of pixels
- }
-
- public void flush() {
- lock.writeLock().lock();
- try {
- map.clear();
- } finally {
- lock.writeLock().unlock();
- }
- }
-
- public Image getImage(final GraphicsConfiguration config, final int w,
- final int h, final int scale,
- final JRSUIState state) {
- final int hash = hash(config, w, h, scale, state);
- final PixelCountSoftReference ref;
- lock.readLock().lock();
- try {
- ref = map.get(hash);
- } finally {
- lock.readLock().unlock();
- }
- // check reference has not been lost and the key truly matches,
- // in case of false positive hash match
- if (ref != null && ref.equals(config, w, h, scale, state)) {
- return ref.get();
- }
- return null;
- }
-
- /**
- * Sets the cached image for the specified constraints.
- *
- * @param image The image to store in cache
- * @param config The graphics configuration, needed if cached image is a Volatile Image. Used as part of cache key
- * @param w The image width, used as part of cache key
- * @param h The image height, used as part of cache key
- * @param scale The image scale factor, used as part of cache key
- * @return true if the image could be cached, false otherwise.
- */
- public boolean setImage(final Image image,
- final GraphicsConfiguration config, final int w, final int h,
- final int scale, final JRSUIState state) {
- if (state.is(JRSUIConstants.Animating.YES)) {
- return false;
- }
-
- final int hash = hash(config, w, h, scale, state);
-
- lock.writeLock().lock();
- try {
- PixelCountSoftReference ref = map.get(hash);
- // check if currently in map
- if (ref != null && ref.get() == image) return true;
-
- // clear out old
- if (ref != null) {
- currentPixelCount -= ref.pixelCount;
- map.remove(hash);
- }
-
- // add new image to pixel count
- final int newPixelCount = image.getWidth(null) * image.getHeight(null);
- currentPixelCount += newPixelCount;
- // clean out lost references if not enough space
- if (currentPixelCount > maxPixelCount) {
- while ((ref = (PixelCountSoftReference)referenceQueue.poll()) != null) {
- //reference lost
- map.remove(ref.hash);
- currentPixelCount -= ref.pixelCount;
- }
- }
-
- // remove old items till there is enough free space
- if (currentPixelCount > maxPixelCount) {
- final Iterator<Map.Entry<Integer, PixelCountSoftReference>> mapIter = map.entrySet().iterator();
- while ((currentPixelCount > maxPixelCount) && mapIter.hasNext()) {
- final Map.Entry<Integer, PixelCountSoftReference> entry = mapIter.next();
- mapIter.remove();
- final Image img = entry.getValue().get();
- if (img != null) img.flush();
- currentPixelCount -= entry.getValue().pixelCount;
- }
- }
- // finally put new in map
- map.put(hash, new PixelCountSoftReference(image, referenceQueue, newPixelCount, hash, config, w, h, scale, state));
- return true;
- } finally {
- lock.writeLock().unlock();
- }
- }
-
- private static int hash(final GraphicsConfiguration config, final int w,
- final int h, final int scale,
- final JRSUIState state) {
- int hash = config != null ? config.hashCode() : 0;
- hash = 31 * hash + w;
- hash = 31 * hash + h;
- hash = 31 * hash + scale;
- hash = 31 * hash + state.hashCode();
- return hash;
- }
-
- /**
- * Extended SoftReference that stores the pixel count even after the image
- * is lost.
- */
- private static class PixelCountSoftReference extends SoftReference<Image> {
-
- // default access, because access to these fields shouldn't be emulated
- // by a synthetic accessor.
- final int pixelCount;
- final int hash;
-
- // key parts
- private final GraphicsConfiguration config;
- private final int w;
- private final int h;
- private final int scale;
- private final JRSUIState state;
-
- PixelCountSoftReference(final Image referent,
- final ReferenceQueue<? super Image> q, final int pixelCount,
- final int hash, final GraphicsConfiguration config, final int w,
- final int h, final int scale, final JRSUIState state) {
- super(referent, q);
- this.pixelCount = pixelCount;
- this.hash = hash;
- this.config = config;
- this.w = w;
- this.h = h;
- this.scale = scale;
- this.state = state;
- }
-
- boolean equals(final GraphicsConfiguration config, final int w,
- final int h, final int scale, final JRSUIState state) {
- return config == this.config && w == this.w && h == this.h
- && scale == this.scale && state.equals(this.state);
- }
- }
-
-// /** Gets the rendered image for this painter at the requested size, either from cache or create a new one */
-// private VolatileImage getImage(GraphicsConfiguration config, JComponent c, int w, int h, Object[] extendedCacheKeys) {
-// VolatileImage buffer = (VolatileImage)getImage(config, w, h, this, extendedCacheKeys);
-//
-// int renderCounter = 0; // to avoid any potential, though unlikely, infinite loop
-// do {
-// //validate the buffer so we can check for surface loss
-// int bufferStatus = VolatileImage.IMAGE_INCOMPATIBLE;
-// if (buffer != null) {
-// bufferStatus = buffer.validate(config);
-// }
-//
-// //If the buffer status is incompatible or restored, then we need to re-render to the volatile image
-// if (bufferStatus == VolatileImage.IMAGE_INCOMPATIBLE || bufferStatus == VolatileImage.IMAGE_RESTORED) {
-// // if the buffer isn't the right size, or has lost its contents, then recreate
-// if (buffer != null) {
-// if (buffer.getWidth() != w || buffer.getHeight() != h || bufferStatus == VolatileImage.IMAGE_INCOMPATIBLE) {
-// // clear any resources related to the old back buffer
-// buffer.flush();
-// buffer = null;
-// }
-// }
-//
-// if (buffer == null) {
-// // recreate the buffer
-// buffer = config.createCompatibleVolatileImage(w, h, Transparency.TRANSLUCENT);
-// // put in cache for future
-// setImage(buffer, config, w, h, this, extendedCacheKeys);
-// }
-//
-// //create the graphics context with which to paint to the buffer
-// Graphics2D bg = buffer.createGraphics();
-//
-// //clear the background before configuring the graphics
-// bg.setComposite(AlphaComposite.Clear);
-// bg.fillRect(0, 0, w, h);
-// bg.setComposite(AlphaComposite.SrcOver);
-// bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-//
-// // paint the painter into buffer
-// paint0(bg, c, w, h, extendedCacheKeys);
-// //close buffer graphics
-// bg.dispose();
-// }
-// } while (buffer.contentsLost() && renderCounter++ < 3);
-//
-// // check if we failed
-// if (renderCounter >= 3) return null;
-//
-// return buffer;
-// }
-}
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CImage.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CImage.java
index 5ea172b..7b0c826 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CImage.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CImage.java
@@ -32,6 +32,7 @@
import java.util.Arrays;
import java.util.List;
import sun.awt.image.MultiResolutionImage;
+import sun.awt.image.MultiResolutionBufferedImage;
import sun.awt.image.SunWritableRaster;
@@ -42,10 +43,11 @@
private static native long nativeCreateNSImageOfFileFromLaunchServices(String file);
private static native long nativeCreateNSImageFromImageName(String name);
private static native long nativeCreateNSImageFromIconSelector(int selector);
- private static native void nativeCopyNSImageIntoArray(long image, int[] buffer, int w, int h);
+ private static native void nativeCopyNSImageIntoArray(long image, int[] buffer, int sw, int sh, int dw, int dh);
private static native Dimension2D nativeGetNSImageSize(long image);
private static native void nativeSetNSImageSize(long image, double w, double h);
private static native void nativeResizeNSImageRepresentations(long image, double w, double h);
+ private static native Dimension2D[] nativeGetNSImageRepresentationSizes(long image, double w, double h);
static Creator creator = new Creator();
static Creator getCreator() {
@@ -210,18 +212,30 @@
super(nsImagePtr, true);
}
- /** @return A BufferedImage created from nsImagePtr, or null. */
- public BufferedImage toImage() {
+ /** @return A MultiResolution image created from nsImagePtr, or null. */
+ private BufferedImage toImage() {
if (ptr == 0) return null;
final Dimension2D size = nativeGetNSImageSize(ptr);
final int w = (int)size.getWidth();
final int h = (int)size.getHeight();
- final BufferedImage bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
+ Dimension2D[] sizes
+ = nativeGetNSImageRepresentationSizes(ptr,
+ size.getWidth(), size.getHeight());
+
+ BufferedImage baseImage = toImage(w, h, w, h);
+
+ return sizes == null || sizes.length < 2 ? baseImage
+ : new MultiResolutionBufferedImage(baseImage, sizes,
+ (width, height) -> toImage(w, h, width, height));
+ }
+
+ private BufferedImage toImage(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
+ final BufferedImage bimg = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_ARGB_PRE);
final DataBufferInt dbi = (DataBufferInt)bimg.getRaster().getDataBuffer();
final int[] buffer = SunWritableRaster.stealData(dbi, 0);
- nativeCopyNSImageIntoArray(ptr, buffer, w, h);
+ nativeCopyNSImageIntoArray(ptr, buffer, srcWidth, srcHeight, dstWidth, dstHeight);
SunWritableRaster.markDirty(dbi);
return bimg;
}
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java
index dbc8d73..29f4639 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java
@@ -41,7 +41,7 @@
import sun.java2d.*;
import sun.print.*;
-final class CPrinterJob extends RasterPrinterJob {
+public final class CPrinterJob extends RasterPrinterJob {
// NOTE: This uses RasterPrinterJob as a base, but it doesn't use
// all of the RasterPrinterJob functions. RasterPrinterJob will
// break down printing to pieces that aren't necessary under MacOSX
diff --git a/jdk/src/macosx/native/sun/awt/AWTWindow.m b/jdk/src/macosx/native/sun/awt/AWTWindow.m
index f9a7919..eaf1793 100644
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m
@@ -762,6 +762,10 @@
return lastKeyWindow;
}
+- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame {
+ return !NSEqualSizes(self.nsWindow.frame.size, newFrame.size);
+}
+
@end // AWTWindow
diff --git a/jdk/src/macosx/native/sun/awt/CImage.m b/jdk/src/macosx/native/sun/awt/CImage.m
index de73198..ddcd123 100644
--- a/jdk/src/macosx/native/sun/awt/CImage.m
+++ b/jdk/src/macosx/native/sun/awt/CImage.m
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#import "jni_util.h"
#import <Cocoa/Cocoa.h>
#import <JavaNativeFoundation/JavaNativeFoundation.h>
@@ -52,18 +53,21 @@
}
static void CImage_CopyNSImageIntoArray
-(NSImage *srcImage, jint *dstPixels, int width, int height)
+(NSImage *srcImage, jint *dstPixels, NSRect fromRect, NSRect toRect)
{
+ int width = toRect.size.width;
+ int height = toRect.size.height;
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
- CGContextRef cgRef = CGBitmapContextCreate(dstPixels, width, height, 8, width * 4, colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
+ CGContextRef cgRef = CGBitmapContextCreate(dstPixels, width, height,
+ 8, width * 4, colorspace,
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
CGColorSpaceRelease(colorspace);
NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:cgRef flipped:NO];
CGContextRelease(cgRef);
NSGraphicsContext *oldContext = [[NSGraphicsContext currentContext] retain];
[NSGraphicsContext setCurrentContext:context];
- NSRect rect = NSMakeRect(0, 0, width, height);
- [srcImage drawInRect:rect
- fromRect:rect
+ [srcImage drawInRect:toRect
+ fromRect:fromRect
operation:NSCompositeSourceOver
fraction:1.0];
[NSGraphicsContext setCurrentContext:oldContext];
@@ -266,17 +270,20 @@
/*
* Class: sun_lwawt_macosx_CImage
* Method: nativeCopyNSImageIntoArray
- * Signature: (J[III)V
+ * Signature: (J[IIIII)V
*/
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeCopyNSImageIntoArray
-(JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint w, jint h)
+(JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint sw, jint sh,
+ jint dw, jint dh)
{
JNF_COCOA_ENTER(env);
NSImage *img = (NSImage *)jlong_to_ptr(nsImgPtr);
jint *dst = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL);
if (dst) {
- CImage_CopyNSImageIntoArray(img, dst, w, h);
+ NSRect fromRect = NSMakeRect(0, 0, sw, sh);
+ NSRect toRect = NSMakeRect(0, 0, dw, dh);
+ CImage_CopyNSImageIntoArray(img, dst, fromRect, toRect);
(*env)->ReleasePrimitiveArrayCritical(env, buffer, dst, JNI_ABORT);
}
@@ -343,3 +350,87 @@
JNF_COCOA_EXIT(env);
}
+
+NSComparisonResult getOrder(BOOL order){
+ return (NSComparisonResult) (order ? NSOrderedAscending : NSOrderedDescending);
+}
+
+/*
+ * Class: sun_lwawt_macosx_CImage
+ * Method: nativeGetNSImageRepresentationsCount
+ * Signature: (JDD)[Ljava/awt/geom/Dimension2D;
+ */
+JNIEXPORT jobjectArray JNICALL
+ Java_sun_lwawt_macosx_CImage_nativeGetNSImageRepresentationSizes
+(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h)
+{
+ if (!image) return NULL;
+ jobjectArray jreturnArray = NULL;
+ NSImage *img = (NSImage *)jlong_to_ptr(image);
+
+JNF_COCOA_ENTER(env);
+
+ NSArray *imageRepresentations = [img representations];
+ if([imageRepresentations count] == 0){
+ return NULL;
+ }
+
+ NSArray *sortedImageRepresentations = [imageRepresentations
+ sortedArrayUsingComparator: ^(id obj1, id obj2) {
+
+ NSImageRep *imageRep1 = (NSImageRep *) obj1;
+ NSImageRep *imageRep2 = (NSImageRep *) obj2;
+ NSSize size1 = [imageRep1 size];
+ NSSize size2 = [imageRep2 size];
+
+ if (NSEqualSizes(size1, size2)) {
+ return getOrder([imageRep1 pixelsWide] <= [imageRep2 pixelsWide] &&
+ [imageRep1 pixelsHigh] <= [imageRep2 pixelsHigh]);
+ }
+
+ return getOrder(size1.width <= size2.width && size1.height <= size2.height);
+ }];
+
+ NSMutableArray *sortedPixelSizes = [[[NSMutableArray alloc] init] autorelease];
+ NSSize lastSize = [[sortedImageRepresentations lastObject] size];
+
+ NSUInteger i = [sortedImageRepresentations indexOfObjectPassingTest:
+ ^BOOL(id obj, NSUInteger idx, BOOL *stop) {
+ NSSize imageRepSize = [obj size];
+ return (w <= imageRepSize.width && h <= imageRepSize.height)
+ || NSEqualSizes(imageRepSize, lastSize);
+ }];
+
+ NSUInteger count = [sortedImageRepresentations count];
+ i = (i == NSNotFound) ? count - 1 : i;
+ NSSize bestFitSize = [[sortedImageRepresentations objectAtIndex: i] size];
+
+ for(; i < count; i++){
+ NSImageRep *imageRep = [sortedImageRepresentations objectAtIndex: i];
+
+ if (!NSEqualSizes([imageRep size], bestFitSize)) {
+ break;
+ }
+
+ NSSize pixelSize = NSMakeSize(
+ [imageRep pixelsWide], [imageRep pixelsHigh]);
+ [sortedPixelSizes addObject: [NSValue valueWithSize: pixelSize]];
+ }
+
+ count = [sortedPixelSizes count];
+ static JNF_CLASS_CACHE(jc_Dimension, "java/awt/Dimension");
+ jreturnArray = JNFNewObjectArray(env, &jc_Dimension, count);
+ CHECK_NULL_RETURN(jreturnArray, NULL);
+
+ for(i = 0; i < count; i++){
+ NSSize pixelSize = [[sortedPixelSizes objectAtIndex: i] sizeValue];
+
+ (*env)->SetObjectArrayElement(env, jreturnArray, i,
+ NSToJavaSize(env, pixelSize));
+ JNU_CHECK_EXCEPTION_RETURN(env, NULL);
+ }
+
+JNF_COCOA_EXIT(env);
+
+ return jreturnArray;
+}
\ No newline at end of file
diff --git a/jdk/src/macosx/native/sun/awt/CTextPipe.m b/jdk/src/macosx/native/sun/awt/CTextPipe.m
index a46fd01..434186e 100644
--- a/jdk/src/macosx/native/sun/awt/CTextPipe.m
+++ b/jdk/src/macosx/native/sun/awt/CTextPipe.m
@@ -147,7 +147,7 @@
CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx);
- NSUInteger i;
+ NSInteger i;
for (i = 0; i < length; i++)
{
CGGlyph glyph = glyphs[i];
@@ -355,19 +355,31 @@
static JNF_CLASS_CACHE(jc_StandardGlyphVector_GlyphTransformInfo, "sun/font/StandardGlyphVector$GlyphTransformInfo");
static JNF_MEMBER_CACHE(jm_StandardGlyphVector_GlyphTransformInfo_transforms, jc_StandardGlyphVector_GlyphTransformInfo, "transforms", "[D");
jdoubleArray g_gtiTransformsArray = JNFGetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_transforms); //(*env)->GetObjectField(env, gti, g_gtiTransforms);
+ if (g_gtiTransformsArray == NULL) {
+ return;
+ }
jdouble *g_gvTransformsAsDoubles = (*env)->GetPrimitiveArrayCritical(env, g_gtiTransformsArray, NULL);
+ if (g_gvTransformsAsDoubles == NULL) {
+ (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
+ return;
+ }
static JNF_MEMBER_CACHE(jm_StandardGlyphVector_GlyphTransformInfo_indices, jc_StandardGlyphVector_GlyphTransformInfo, "indices", "[I");
jintArray g_gtiTXIndicesArray = JNFGetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_indices);
jint *g_gvTXIndicesAsInts = (*env)->GetPrimitiveArrayCritical(env, g_gtiTXIndicesArray, NULL);
-
+ if (g_gvTXIndicesAsInts == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT);
+ (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
+ (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
+ return;
+ }
// slowest case, we have per-glyph transforms, and possibly glyph substitution as well
JavaCT_DrawGlyphVector(qsdo, strike, useSubstituion, uniChars, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length);
(*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT);
- (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
-
(*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT);
+
+ (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
(*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
}
@@ -403,6 +415,9 @@
{
// fill the glyph buffer
jint *glyphsAsInts = (*env)->GetPrimitiveArrayCritical(env, glyphsArray, NULL);
+ if (glyphsAsInts == NULL) {
+ return;
+ }
// if a glyph code from Java is negative, that means it is really a unicode value
// which we can use in CoreText to strike the character in another font
@@ -429,11 +444,15 @@
// fill the advance buffer
static JNF_MEMBER_CACHE(jm_StandardGlyphVector_positions, jc_StandardGlyphVector, "positions", "[F");
jfloatArray posArray = JNFGetObjectField(env, gVector, jm_StandardGlyphVector_positions);
- if (posArray != NULL)
- {
+ jfloat *positions = NULL;
+ if (posArray != NULL) {
// in this case, the positions have already been pre-calculated for us on the Java side
-
- jfloat *positions = (*env)->GetPrimitiveArrayCritical(env, posArray, NULL);
+ positions = (*env)->GetPrimitiveArrayCritical(env, posArray, NULL);
+ if (positions == NULL) {
+ (*env)->DeleteLocalRef(env, posArray);
+ }
+ }
+ if (positions != NULL) {
CGPoint prev;
prev.x = positions[0];
prev.y = positions[1];
diff --git a/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m b/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
index 2d3669f..df2d98d 100644
--- a/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
+++ b/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
@@ -849,7 +849,7 @@
indexOfBest = 0;
distanceOfBest = DBL_MAX;
- for (i=0; i<lutDataSize; i++)
+ for (i=0; (unsigned)i<lutDataSize; i++)
{
p2 = lutdata[i];
@@ -899,7 +899,7 @@
{
if (data != NULL)
{
- free(data);
+ free((void*)data);
}
}
@@ -1577,7 +1577,9 @@
{
static char *bimgName = "java/awt/image/BufferedImage";
jclass bimg = (*env)->FindClass(env, bimgName);
+ CHECK_NULL_RETURN(bimg, NULL);
sDataID = (*env)->GetFieldID(env, bimg, "sData", "Lsun/java2d/SurfaceData;");
+ CHECK_NULL_RETURN(sDataID, NULL);
}
return (*env)->GetObjectField(env, bufImg, sDataID);
@@ -1591,7 +1593,9 @@
{
static char *bimgName = "java/awt/image/BufferedImage";
jclass bimg = (*env)->FindClass(env, bimgName);
+ CHECK_NULL(bimg);
sDataID = (*env)->GetFieldID(env, bimg, "sData", "Lsun/java2d/SurfaceData;");
+ CHECK_NULL(sDataID);
}
(*env)->SetObjectField(env, bufImg, sDataID, sData);
@@ -1610,18 +1614,11 @@
return;
}
- icm = (*env)->FindClass(env, icmName);
- if (icm == NULL) {
- return;
- }
-
- rgbID = (*env)->GetFieldID(env, icm, "rgb", "[I");
- allGrayID = (*env)->GetFieldID(env, icm, "allgrayopaque", "Z");
- mapSizeID = (*env)->GetFieldID(env, icm, "map_size", "I");
- CMpDataID = (*env)->GetFieldID(env, icm, "pData", "J");
- if (allGrayID == 0 || rgbID == 0 || mapSizeID == 0 || CMpDataID == 0) {
- JNU_ThrowInternalError(env, "Could not get field IDs");
- }
+ CHECK_NULL(icm = (*env)->FindClass(env, icmName));
+ CHECK_NULL(rgbID = (*env)->GetFieldID(env, icm, "rgb", "[I"));
+ CHECK_NULL(allGrayID = (*env)->GetFieldID(env, icm, "allgrayopaque", "Z"));
+ CHECK_NULL(mapSizeID = (*env)->GetFieldID(env, icm, "map_size", "I"));
+ CHECK_NULL(CMpDataID = (*env)->GetFieldID(env, icm, "pData", "J"));
}
gColorspaceRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
@@ -1795,6 +1792,7 @@
//bisdo->sdOps.Dispose = BufImg_Dispose;
bisdo->array = (*env)->NewWeakGlobalRef(env, array);
+ if (array != NULL) CHECK_NULL(bisdo->array);
bisdo->offset = offset;
//bisdo->scanStr = scanStr;
bisdo->scanStr = scanStride;
@@ -1807,8 +1805,10 @@
} else {
jobject lutarray = (*env)->GetObjectField(env, icm, rgbID);
bisdo->lutarray = (*env)->NewWeakGlobalRef(env, lutarray);
+ if (lutarray != NULL) CHECK_NULL(bisdo->lutarray);
bisdo->lutsize = (*env)->GetIntField(env, icm, mapSizeID);
bisdo->icm = (*env)->NewWeakGlobalRef(env, icm);
+ if (icm != NULL) CHECK_NULL(bisdo->icm);
}
bisdo->rasbounds.x1 = 0;
bisdo->rasbounds.y1 = 0;
@@ -1887,7 +1887,7 @@
Pixel32bit* src = lutdata;
Pixel32bit* dst = isdo->lutData;
jint i;
- for (i=0; i<isdo->lutDataSize; i++)
+ for (i=0; (unsigned)i<isdo->lutDataSize; i++)
{
if (i != transparent_index)
{
@@ -1919,7 +1919,7 @@
Pixel32bit* src = lutdata;
Pixel32bit* dst = isdo->lutData;
jint i;
- for (i=0; i<isdo->lutDataSize; i++)
+ for (i=0; (unsigned)i<isdo->lutDataSize; i++)
{
*dst = *src | mask;
dst++; src++;
diff --git a/jdk/src/macosx/native/sun/awt/QuartzRenderer.m b/jdk/src/macosx/native/sun/awt/QuartzRenderer.m
index d87582c..27f31c2 100644
--- a/jdk/src/macosx/native/sun/awt/QuartzRenderer.m
+++ b/jdk/src/macosx/native/sun/awt/QuartzRenderer.m
@@ -438,6 +438,9 @@
{
SDRenderType renderType = SD_Nothing;
+ if (xpointsarray == NULL || ypointsarray == NULL) {
+ return SD_Nothing;
+ }
if (npoints > 1)
{
if (fill == YES)
@@ -452,7 +455,14 @@
jint i;
jint* xpoints = (jint*)(*env)->GetPrimitiveArrayCritical(env, xpointsarray, NULL);
+ if (xpoints == NULL) {
+ return SD_Nothing;
+ }
jint* ypoints = (jint*)(*env)->GetPrimitiveArrayCritical(env, ypointsarray, NULL);
+ if (ypoints == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, xpointsarray, xpoints, 0);
+ return SD_Nothing;
+ }
CGContextMoveToPoint(cgRef, xpoints[0]+offsetX, ypoints[0]+offsetY);
diff --git a/jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m b/jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m
index dd61d0a..131dc1e 100644
--- a/jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m
+++ b/jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m
@@ -778,6 +778,10 @@
qsdo->graphicsStateInfo.simpleStroke = NO;
jint length = (*env)->GetArrayLength(env, dasharray);
jfloat* jdashes = (jfloat*)(*env)->GetPrimitiveArrayCritical(env, dasharray, NULL);
+ if (jdashes == NULL) {
+ CGContextSetLineDash(cgRef, 0, NULL, 0);
+ return;
+ }
CGFloat* dashes = (CGFloat*)malloc(sizeof(CGFloat)*length);
if (dashes != NULL)
{
diff --git a/jdk/src/macosx/native/sun/font/AWTStrike.m b/jdk/src/macosx/native/sun/font/AWTStrike.m
index 6e4b429..f26c5e1 100644
--- a/jdk/src/macosx/native/sun/font/AWTStrike.m
+++ b/jdk/src/macosx/native/sun/font/AWTStrike.m
@@ -127,6 +127,9 @@
}
jdouble *txPtr = (*env)->GetPrimitiveArrayCritical(env, txArray, NULL);
+ if (txPtr == NULL) {
+ return CGAffineTransformIdentity;
+ }
CGAffineTransform tx =
CGAffineTransformMake(txPtr[0], txPtr[1], txPtr[2],
@@ -311,18 +314,22 @@
jlong *glyphInfos =
(*env)->GetPrimitiveArrayCritical(env, glyphInfoLongArray, NULL);
+ if (glyphInfos != NULL) {
jint *rawGlyphCodes =
(*env)->GetPrimitiveArrayCritical(env, glyphCodes, NULL);
+ if (rawGlyphCodes != NULL) {
CGGlyphImages_GetGlyphImagePtrs(glyphInfos, awtStrike,
rawGlyphCodes, len);
(*env)->ReleasePrimitiveArrayCritical(env, glyphCodes,
rawGlyphCodes, JNI_ABORT);
+ }
// Do not use JNI_COMMIT, as that will not free the buffer copy
// when +ProtectJavaHeap is on.
(*env)->ReleasePrimitiveArrayCritical(env, glyphInfoLongArray,
glyphInfos, 0);
+ }
JNF_COCOA_EXIT(env);
}
diff --git a/jdk/src/macosx/native/sun/font/CCharToGlyphMapper.m b/jdk/src/macosx/native/sun/font/CCharToGlyphMapper.m
index cf08137..81fb69d 100644
--- a/jdk/src/macosx/native/sun/font/CCharToGlyphMapper.m
+++ b/jdk/src/macosx/native/sun/font/CCharToGlyphMapper.m
@@ -101,10 +101,13 @@
jchar *unicodesAsChars =
(*env)->GetPrimitiveArrayCritical(env, unicodes, NULL);
- AllocateGlyphBuffer(env, awtFont, count, (UniChar *)unicodesAsChars, glyphs);
+ if (unicodesAsChars != NULL) {
+ AllocateGlyphBuffer(env, awtFont, count,
+ (UniChar *)unicodesAsChars, glyphs);
(*env)->ReleasePrimitiveArrayCritical(env, unicodes,
unicodesAsChars, JNI_ABORT);
+ }
JNF_COCOA_EXIT(env);
}
diff --git a/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java b/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java
index 305672b..68379a7 100644
--- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java
+++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java
@@ -787,6 +787,14 @@
if (!reconnected) {
try {
NotificationResult nr = fetchNotifs(-1, 0, 0);
+
+ if (state != STOPPED) { // JDK-8038940
+ // reconnection must happen during
+ // fetchNotifs(-1, 0, 0), and a new
+ // thread takes over the fetching job
+ return;
+ }
+
clientSequenceNumber = nr.getNextSequenceNumber();
} catch (ClassNotFoundException e) {
// can't happen
diff --git a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
index a6bb5ec..434f3e3 100644
--- a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
+++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
@@ -861,4 +861,18 @@
* All subclasses must provide such a value describing their type signature.
*/
static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
+
+ private static final SpeciesData[] SPECIES_DATA_CACHE = new SpeciesData[5];
+ private static SpeciesData checkCache(int size, String types) {
+ int idx = size - 1;
+ SpeciesData data = SPECIES_DATA_CACHE[idx];
+ if (data != null) return data;
+ SPECIES_DATA_CACHE[idx] = data = getSpeciesData(types);
+ return data;
+ }
+ static SpeciesData speciesData_L() { return checkCache(1, "L"); }
+ static SpeciesData speciesData_LL() { return checkCache(2, "LL"); }
+ static SpeciesData speciesData_LLL() { return checkCache(3, "LLL"); }
+ static SpeciesData speciesData_LLLL() { return checkCache(4, "LLLL"); }
+ static SpeciesData speciesData_LLLLL() { return checkCache(5, "LLLLL"); }
}
diff --git a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
index 6a79291..bc3340c 100644
--- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
@@ -27,7 +27,6 @@
import sun.invoke.util.VerifyAccess;
import java.lang.invoke.LambdaForm.Name;
-import java.lang.invoke.MethodHandles.Lookup;
import sun.invoke.util.Wrapper;
@@ -39,8 +38,6 @@
import java.lang.reflect.*;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
-import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
-import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyType;
/**
@@ -51,7 +48,7 @@
class InvokerBytecodeGenerator {
/** Define class names for convenience. */
private static final String MH = "java/lang/invoke/MethodHandle";
- private static final String BMH = "java/lang/invoke/BoundMethodHandle";
+ private static final String MHI = "java/lang/invoke/MethodHandleImpl";
private static final String LF = "java/lang/invoke/LambdaForm";
private static final String LFN = "java/lang/invoke/LambdaForm$Name";
private static final String CLS = "java/lang/Class";
@@ -61,6 +58,7 @@
private static final String LF_SIG = "L" + LF + ";";
private static final String LFN_SIG = "L" + LFN + ";";
private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";";
+ private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";";
/** Name of its super class*/
private static final String superName = LF;
@@ -437,7 +435,7 @@
mv.visitLdcInsn(constantPlaceholder(pclass));
mv.visitTypeInsn(Opcodes.CHECKCAST, CLS);
mv.visitInsn(Opcodes.SWAP);
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CLS, "cast", LL_SIG);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG);
if (pclass.isArray())
mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY);
}
@@ -511,17 +509,22 @@
Name name = lambdaForm.names[i];
MemberName member = name.function.member();
- if (isSelectAlternative(member)) {
- // selectAlternative idiom
- // FIXME: make sure this idiom is really present!
+ if (isSelectAlternative(i)) {
emitSelectAlternative(name, lambdaForm.names[i + 1]);
i++; // skip MH.invokeBasic of the selectAlternative result
+ } else if (isGuardWithCatch(i)) {
+ emitGuardWithCatch(i);
+ i = i+2; // Jump to the end of GWC idiom
} else if (isStaticallyInvocable(member)) {
emitStaticInvoke(member, name);
} else {
emitInvoke(name);
}
+ // Update cached form name's info in case an intrinsic spanning multiple names was encountered.
+ name = lambdaForm.names[i];
+ member = name.function.member();
+
// store the result from evaluating to the target name in a local if required
// (if this is the last value, i.e., the one that is going to be returned,
// avoid store/load/return and just return)
@@ -674,12 +677,66 @@
}
/**
- * Check if MemberName is a call to MethodHandleImpl.selectAlternative.
+ * Check if MemberName is a call to a method named {@code name} in class {@code declaredClass}.
*/
- private boolean isSelectAlternative(MemberName member) {
+ private boolean memberRefersTo(MemberName member, Class<?> declaringClass, String name) {
return member != null &&
- member.getDeclaringClass() == MethodHandleImpl.class &&
- member.getName().equals("selectAlternative");
+ member.getDeclaringClass() == declaringClass &&
+ member.getName().equals(name);
+ }
+ private boolean nameRefersTo(Name name, Class<?> declaringClass, String methodName) {
+ return name.function != null &&
+ memberRefersTo(name.function.member(), declaringClass, methodName);
+ }
+
+ /**
+ * Check if MemberName is a call to MethodHandle.invokeBasic.
+ */
+ private boolean isInvokeBasic(Name name) {
+ if (name.function == null)
+ return false;
+ if (name.arguments.length < 1)
+ return false; // must have MH argument
+ MemberName member = name.function.member();
+ return memberRefersTo(member, MethodHandle.class, "invokeBasic") &&
+ !member.isPublic() && !member.isStatic();
+ }
+
+ /**
+ * Check if i-th name is a call to MethodHandleImpl.selectAlternative.
+ */
+ private boolean isSelectAlternative(int pos) {
+ // selectAlternative idiom:
+ // t_{n}:L=MethodHandleImpl.selectAlternative(...)
+ // t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...)
+ if (pos+1 >= lambdaForm.names.length) return false;
+ Name name0 = lambdaForm.names[pos];
+ Name name1 = lambdaForm.names[pos+1];
+ return nameRefersTo(name0, MethodHandleImpl.class, "selectAlternative") &&
+ isInvokeBasic(name1) &&
+ name1.lastUseIndex(name0) == 0 && // t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...)
+ lambdaForm.lastUseIndex(name0) == pos+1; // t_{n} is local: used only in t_{n+1}
+ }
+
+ /**
+ * Check if i-th name is a start of GuardWithCatch idiom.
+ */
+ private boolean isGuardWithCatch(int pos) {
+ // GuardWithCatch idiom:
+ // t_{n}:L=MethodHandle.invokeBasic(...)
+ // t_{n+1}:L=MethodHandleImpl.guardWithCatch(*, *, *, t_{n});
+ // t_{n+2}:?=MethodHandle.invokeBasic(t_{n+1})
+ if (pos+2 >= lambdaForm.names.length) return false;
+ Name name0 = lambdaForm.names[pos];
+ Name name1 = lambdaForm.names[pos+1];
+ Name name2 = lambdaForm.names[pos+2];
+ return nameRefersTo(name1, MethodHandleImpl.class, "guardWithCatch") &&
+ isInvokeBasic(name0) &&
+ isInvokeBasic(name2) &&
+ name1.lastUseIndex(name0) == 3 && // t_{n+1}:L=MethodHandleImpl.guardWithCatch(*, *, *, t_{n});
+ lambdaForm.lastUseIndex(name0) == pos+1 && // t_{n} is local: used only in t_{n+1}
+ name2.lastUseIndex(name1) == 1 && // t_{n+2}:?=MethodHandle.invokeBasic(t_{n+1})
+ lambdaForm.lastUseIndex(name1) == pos+2; // t_{n+1} is local: used only in t_{n+2}
}
/**
@@ -694,8 +751,6 @@
* }</pre></blockquote>
*/
private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) {
- MethodType type = selectAlternativeName.function.methodType();
-
Name receiver = (Name) invokeBasicName.arguments[0];
Label L_fallback = new Label();
@@ -709,7 +764,6 @@
mv.visitJumpInsn(Opcodes.IF_ICMPNE, L_fallback);
// invoke selectAlternativeName.arguments[1]
- MethodHandle target = (MethodHandle) selectAlternativeName.arguments[1];
emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative
emitAstoreInsn(receiver.index()); // store the MH in the receiver slot
emitInvoke(invokeBasicName);
@@ -721,7 +775,6 @@
mv.visitLabel(L_fallback);
// invoke selectAlternativeName.arguments[2]
- MethodHandle fallback = (MethodHandle) selectAlternativeName.arguments[2];
emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative
emitAstoreInsn(receiver.index()); // store the MH in the receiver slot
emitInvoke(invokeBasicName);
@@ -730,6 +783,85 @@
mv.visitLabel(L_done);
}
+ /**
+ * Emit bytecode for the guardWithCatch idiom.
+ *
+ * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithCatch):
+ * <blockquote><pre>{@code
+ * guardWithCatch=Lambda(a0:L,a1:L,a2:L,a3:L,a4:L,a5:L,a6:L,a7:L)=>{
+ * t8:L=MethodHandle.invokeBasic(a4:L,a6:L,a7:L);
+ * t9:L=MethodHandleImpl.guardWithCatch(a1:L,a2:L,a3:L,t8:L);
+ * t10:I=MethodHandle.invokeBasic(a5:L,t9:L);t10:I}
+ * }</pre></blockquote>
+ *
+ * It is compiled into bytecode equivalent of the following code:
+ * <blockquote><pre>{@code
+ * try {
+ * return a1.invokeBasic(a6, a7);
+ * } catch (Throwable e) {
+ * if (!a2.isInstance(e)) throw e;
+ * return a3.invokeBasic(ex, a6, a7);
+ * }}
+ */
+ private void emitGuardWithCatch(int pos) {
+ Name args = lambdaForm.names[pos];
+ Name invoker = lambdaForm.names[pos+1];
+ Name result = lambdaForm.names[pos+2];
+
+ Label L_startBlock = new Label();
+ Label L_endBlock = new Label();
+ Label L_handler = new Label();
+ Label L_done = new Label();
+
+ Class<?> returnType = result.function.resolvedHandle.type().returnType();
+ MethodType type = args.function.resolvedHandle.type()
+ .dropParameterTypes(0,1)
+ .changeReturnType(returnType);
+
+ mv.visitTryCatchBlock(L_startBlock, L_endBlock, L_handler, "java/lang/Throwable");
+
+ // Normal case
+ mv.visitLabel(L_startBlock);
+ // load target
+ emitPushArgument(invoker, 0);
+ emitPushArguments(args, 1); // skip 1st argument: method handle
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false);
+ mv.visitLabel(L_endBlock);
+ mv.visitJumpInsn(Opcodes.GOTO, L_done);
+
+ // Exceptional case
+ mv.visitLabel(L_handler);
+
+ // Check exception's type
+ mv.visitInsn(Opcodes.DUP);
+ // load exception class
+ emitPushArgument(invoker, 1);
+ mv.visitInsn(Opcodes.SWAP);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "isInstance", "(Ljava/lang/Object;)Z", false);
+ Label L_rethrow = new Label();
+ mv.visitJumpInsn(Opcodes.IFEQ, L_rethrow);
+
+ // Invoke catcher
+ // load catcher
+ emitPushArgument(invoker, 2);
+ mv.visitInsn(Opcodes.SWAP);
+ emitPushArguments(args, 1); // skip 1st argument: method handle
+ MethodType catcherType = type.insertParameterTypes(0, Throwable.class);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", catcherType.basicType().toMethodDescriptorString(), false);
+ mv.visitJumpInsn(Opcodes.GOTO, L_done);
+
+ mv.visitLabel(L_rethrow);
+ mv.visitInsn(Opcodes.ATHROW);
+
+ mv.visitLabel(L_done);
+ }
+
+ private void emitPushArguments(Name args, int start) {
+ for (int i = start; i < args.arguments.length; i++) {
+ emitPushArgument(args, i);
+ }
+ }
+
private void emitPushArgument(Name name, int paramIndex) {
Object arg = name.arguments[paramIndex];
char ptype = name.function.parameterType(paramIndex);
diff --git a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java
index c3ab19f..a5e40ed 100644
--- a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java
+++ b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java
@@ -1465,6 +1465,33 @@
return false;
}
+ /** Return the index of the last occurrence of n in the argument array.
+ * Return -1 if the name is not used.
+ */
+ int lastUseIndex(Name n) {
+ if (arguments == null) return -1;
+ for (int i = arguments.length; --i >= 0; ) {
+ if (arguments[i] == n) return i;
+ }
+ return -1;
+ }
+
+ /** Return the number of occurrences of n in the argument array.
+ * Return 0 if the name is not used.
+ */
+ int useCount(Name n) {
+ if (arguments == null) return 0;
+ int count = 0;
+ for (int i = arguments.length; --i >= 0; ) {
+ if (arguments[i] == n) ++count;
+ }
+ return count;
+ }
+
+ boolean contains(Name n) {
+ return this == n || lastUseIndex(n) >= 0;
+ }
+
public boolean equals(Name that) {
if (this == that) return true;
if (isParam())
@@ -1488,6 +1515,35 @@
}
}
+ /** Return the index of the last name which contains n as an argument.
+ * Return -1 if the name is not used. Return names.length if it is the return value.
+ */
+ int lastUseIndex(Name n) {
+ int ni = n.index, nmax = names.length;
+ assert(names[ni] == n);
+ if (result == ni) return nmax; // live all the way beyond the end
+ for (int i = nmax; --i > ni; ) {
+ if (names[i].lastUseIndex(n) >= 0)
+ return i;
+ }
+ return -1;
+ }
+
+ /** Return the number of times n is used as an argument or return value. */
+ int useCount(Name n) {
+ int ni = n.index, nmax = names.length;
+ int end = lastUseIndex(n);
+ if (end < 0) return 0;
+ int count = 0;
+ if (end == nmax) { count++; end--; }
+ int beg = n.index() + 1;
+ if (beg < arity) beg = arity;
+ for (int i = beg; i <= end; i++) {
+ count += names[i].useCount(n);
+ }
+ return count;
+ }
+
static Name argument(int which, char type) {
int tn = ALL_TYPES.indexOf(type);
if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT)
diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
index eca236c..cdf6e5a 100644
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -27,7 +27,6 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import sun.invoke.empty.Empty;
@@ -254,7 +253,7 @@
// Note: Do not check for a class hierarchy relation
// between src and dst. In all cases a 'null' argument
// will pass the cast conversion.
- fn = ValueConversions.cast(dst);
+ fn = ValueConversions.cast(dst, Lazy.MH_castReference);
}
}
Name conv = new Name(fn, names[INARG_BASE + i]);
@@ -294,6 +293,25 @@
return SimpleMethodHandle.make(srcType, form);
}
+ /**
+ * Identity function, with reference cast.
+ * @param t an arbitrary reference type
+ * @param x an arbitrary reference value
+ * @return the same value x
+ */
+ @ForceInline
+ @SuppressWarnings("unchecked")
+ static <T,U> T castReference(Class<? extends T> t, U x) {
+ // inlined Class.cast because we can't ForceInline it
+ if (x != null && !t.isInstance(x))
+ throw newClassCastException(t, x);
+ return (T) x;
+ }
+
+ private static ClassCastException newClassCastException(Class<?> t, Object obj) {
+ return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
+ }
+
static MethodHandle makeReferenceIdentity(Class<?> refType) {
MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
Name[] names = arguments(1, lambdaType);
@@ -482,12 +500,31 @@
* Factored in an inner class to delay initialization until first usage.
*/
private static class Lazy {
+ private static final Class<?> MHI = MethodHandleImpl.class;
+
static final NamedFunction NF_checkSpreadArgument;
+ static final NamedFunction NF_guardWithCatch;
+ static final NamedFunction NF_selectAlternative;
+ static final NamedFunction NF_throwException;
+
+ static final MethodHandle MH_castReference;
+
static {
try {
- NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class
- .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
+ NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
+ NF_guardWithCatch = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
+ MethodHandle.class, Object[].class));
+ NF_selectAlternative = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class,
+ MethodHandle.class));
+ NF_throwException = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
+
NF_checkSpreadArgument.resolve();
+ NF_guardWithCatch.resolve();
+ NF_selectAlternative.resolve();
+ NF_throwException.resolve();
+
+ MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class);
+ MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt);
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}
@@ -548,24 +585,12 @@
return SimpleMethodHandle.make(srcType, form);
}
+ @LambdaForm.Hidden
static
MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
return testResult ? target : fallback;
}
- static MethodHandle SELECT_ALTERNATIVE;
- static MethodHandle selectAlternative() {
- if (SELECT_ALTERNATIVE != null) return SELECT_ALTERNATIVE;
- try {
- SELECT_ALTERNATIVE
- = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
- MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
- } catch (ReflectiveOperationException ex) {
- throw new RuntimeException(ex);
- }
- return SELECT_ALTERNATIVE;
- }
-
static
MethodHandle makeGuardWithTest(MethodHandle test,
MethodHandle target,
@@ -585,7 +610,7 @@
// call selectAlternative
Object[] selectArgs = { names[arity + 1], target, fallback };
- names[arity + 2] = new Name(MethodHandleImpl.selectAlternative(), selectArgs);
+ names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs);
targetArgs[0] = names[arity + 2];
// call target or fallback
@@ -595,167 +620,138 @@
return SimpleMethodHandle.make(target.type(), form);
}
- private static class GuardWithCatch {
- private final MethodHandle target;
- private final Class<? extends Throwable> exType;
- private final MethodHandle catcher;
- // FIXME: Build the control flow out of foldArguments.
- GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
- this.target = target;
- this.exType = exType;
- this.catcher = catcher;
- }
- @LambdaForm.Hidden
- private Object invoke_V(Object... av) throws Throwable {
- try {
- return target.invokeExact(av);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, av);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L0() throws Throwable {
- try {
- return target.invokeExact();
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L1(Object a0) throws Throwable {
- try {
- return target.invokeExact(a0);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L2(Object a0, Object a1) throws Throwable {
- try {
- return target.invokeExact(a0, a1);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3, a4);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3, a4);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3, a4, a5);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
- }
- }
- @LambdaForm.Hidden
- private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
- }
- }
- static MethodHandle[] makeInvokes() {
- ArrayList<MethodHandle> invokes = new ArrayList<>();
- MethodHandles.Lookup lookup = IMPL_LOOKUP;
- for (;;) {
- int nargs = invokes.size();
- String name = "invoke_L"+nargs;
- MethodHandle invoke = null;
- try {
- invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
- } catch (ReflectiveOperationException ex) {
- }
- if (invoke == null) break;
- invokes.add(invoke);
- }
- assert(invokes.size() == 9); // current number of methods
- return invokes.toArray(new MethodHandle[0]);
- };
- static final MethodHandle[] INVOKES = makeInvokes();
- // For testing use this:
- //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
- static final MethodHandle VARARGS_INVOKE;
- static {
- try {
- VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- }
- }
+ /**
+ * The LambaForm shape for catchException combinator is the following:
+ * <blockquote><pre>{@code
+ * guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
+ * t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
+ * t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
+ * t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
+ * t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
+ * t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
+ * t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
+ * t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
+ * t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
+ * }</pre></blockquote>
+ *
+ * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
+ * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
+ * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
+ *
+ * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms
+ * among catchException combinators with the same basic type.
+ */
+ private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
+ MethodType lambdaType = basicType.invokerType();
+ LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC);
+ if (lform != null) {
+ return lform;
+ }
+ final int THIS_MH = 0; // the BMH_LLLLL
+ final int ARG_BASE = 1; // start of incoming arguments
+ final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
+
+ int nameCursor = ARG_LIMIT;
+ final int GET_TARGET = nameCursor++;
+ final int GET_CLASS = nameCursor++;
+ final int GET_CATCHER = nameCursor++;
+ final int GET_COLLECT_ARGS = nameCursor++;
+ final int GET_UNBOX_RESULT = nameCursor++;
+ final int BOXED_ARGS = nameCursor++;
+ final int TRY_CATCH = nameCursor++;
+ final int UNBOX_RESULT = nameCursor++;
+
+ Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
+
+ BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
+ names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]);
+ names[GET_CLASS] = new Name(data.getterFunction(1), names[THIS_MH]);
+ names[GET_CATCHER] = new Name(data.getterFunction(2), names[THIS_MH]);
+ names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]);
+ names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]);
+
+ // FIXME: rework argument boxing/result unboxing logic for LF interpretation
+
+ // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...);
+ MethodType collectArgsType = basicType.changeReturnType(Object.class);
+ MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
+ Object[] args = new Object[invokeBasic.type().parameterCount()];
+ args[0] = names[GET_COLLECT_ARGS];
+ System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
+ names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args);
+
+ // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L);
+ Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
+ names[TRY_CATCH] = new Name(Lazy.NF_guardWithCatch, gwcArgs);
+
+ // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
+ MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
+ Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
+ names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs);
+
+ lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
+
+ basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
+ return lform;
+ }
static
MethodHandle makeGuardWithCatch(MethodHandle target,
Class<? extends Throwable> exType,
MethodHandle catcher) {
MethodType type = target.type();
- MethodType ctype = catcher.type();
- int nargs = type.parameterCount();
- if (nargs < GuardWithCatch.INVOKES.length) {
- MethodType gtype = type.generic();
- MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
- // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
- MethodHandle gtarget = makePairwiseConvert(target, gtype, 2);
- MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2);
- GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
- if (gtarget == null || gcatcher == null) throw new InternalError();
- MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard);
- return makePairwiseConvert(ginvoker, type, 2);
+ LambdaForm form = makeGuardWithCatchForm(type.basicType());
+
+ // Prepare auxiliary method handles used during LambdaForm interpreation.
+ // Box arguments and wrap them into Object[]: ValueConversions.array().
+ MethodType varargsType = type.changeReturnType(Object[].class);
+ MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount())
+ .asType(varargsType);
+ // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
+ MethodHandle unboxResult;
+ if (type.returnType().isPrimitive()) {
+ unboxResult = ValueConversions.unbox(type.returnType());
} else {
- target = target.asType(type.changeReturnType(Object.class));
- MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs);
- MethodType catcherType = ctype.changeParameterType(0, Throwable.class)
- .changeReturnType(Object.class);
- catcher = catcher.asType(catcherType);
- MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs);
- GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
- if (gtarget == null || gcatcher == null) throw new InternalError();
- MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard);
- MethodHandle gcollect = makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false);
- return makePairwiseConvert(gcollect, type, 2);
+ unboxResult = ValueConversions.identity();
}
+
+ BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
+ BoundMethodHandle mh;
+ try {
+ mh = (BoundMethodHandle)
+ data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
+ (Object) collectArgs, (Object) unboxResult);
+ } catch (Throwable ex) {
+ throw uncaughtException(ex);
+ }
+ assert(mh.type() == type);
+ return mh;
+ }
+
+ /**
+ * Intrinsified during LambdaForm compilation
+ * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
+ */
+ @LambdaForm.Hidden
+ static Object guardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher,
+ Object... av) throws Throwable {
+ // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
+ try {
+ return target.asFixedArity().invokeWithArguments(av);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.asFixedArity().invokeWithArguments(prepend(t, av));
+ }
+ }
+
+ /** Prepend an element {@code elem} to an {@code array}. */
+ @LambdaForm.Hidden
+ private static Object[] prepend(Object elem, Object[] array) {
+ Object[] newArray = new Object[array.length+1];
+ newArray[0] = elem;
+ System.arraycopy(array, 0, newArray, 1, array.length);
+ return newArray;
}
static
@@ -765,23 +761,9 @@
if (arity > 1) {
return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
}
- return makePairwiseConvert(throwException(), type, 2);
+ return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2);
}
- static MethodHandle THROW_EXCEPTION;
- static MethodHandle throwException() {
- MethodHandle mh = THROW_EXCEPTION;
- if (mh != null) return mh;
- try {
- mh
- = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
- MethodType.methodType(Empty.class, Throwable.class));
- } catch (ReflectiveOperationException ex) {
- throw new RuntimeException(ex);
- }
- THROW_EXCEPTION = mh;
- return mh;
- }
static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
diff --git a/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java
index 80a751c..ee5e622 100644
--- a/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java
@@ -76,7 +76,8 @@
LF_GEN_INVOKER = 12,
LF_CS_LINKER = 13, // linkToCallSite_CS
LF_MH_LINKER = 14, // linkToCallSite_MH
- LF_LIMIT = 15;
+ LF_GWC = 15,
+ LF_LIMIT = 16;
public MethodType erasedType() {
return erasedType;
diff --git a/jdk/src/share/classes/java/util/Arrays.java b/jdk/src/share/classes/java/util/Arrays.java
index 914879c..7f6cc1d 100644
--- a/jdk/src/share/classes/java/util/Arrays.java
+++ b/jdk/src/share/classes/java/util/Arrays.java
@@ -28,6 +28,7 @@
import java.lang.reflect.Array;
import java.util.concurrent.ForkJoinPool;
import java.util.function.BinaryOperator;
+import java.util.function.Consumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.IntBinaryOperator;
import java.util.function.IntFunction;
@@ -35,6 +36,7 @@
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.LongBinaryOperator;
+import java.util.function.UnaryOperator;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
@@ -3848,12 +3850,13 @@
@Override
public int indexOf(Object o) {
- if (o==null) {
- for (int i=0; i<a.length; i++)
- if (a[i]==null)
+ E[] a = this.a;
+ if (o == null) {
+ for (int i = 0; i < a.length; i++)
+ if (a[i] == null)
return i;
} else {
- for (int i=0; i<a.length; i++)
+ for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
@@ -3869,6 +3872,28 @@
public Spliterator<E> spliterator() {
return Spliterators.spliterator(a, Spliterator.ORDERED);
}
+
+ @Override
+ public void forEach(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ for (E e : a) {
+ action.accept(e);
+ }
+ }
+
+ @Override
+ public void replaceAll(UnaryOperator<E> operator) {
+ Objects.requireNonNull(operator);
+ E[] a = this.a;
+ for (int i = 0; i < a.length; i++) {
+ a[i] = operator.apply(a[i]);
+ }
+ }
+
+ @Override
+ public void sort(Comparator<? super E> c) {
+ Arrays.sort(a, c);
+ }
}
/**
diff --git a/jdk/src/share/classes/java/util/Spliterators.java b/jdk/src/share/classes/java/util/Spliterators.java
index 3f97a83..79c0ef3 100644
--- a/jdk/src/share/classes/java/util/Spliterators.java
+++ b/jdk/src/share/classes/java/util/Spliterators.java
@@ -384,7 +384,7 @@
*/
private static void checkFromToBounds(int arrayLength, int origin, int fence) {
if (origin > fence) {
- throw new IllegalArgumentException(
+ throw new ArrayIndexOutOfBoundsException(
"origin(" + origin + ") > fence(" + fence + ")");
}
if (origin < 0) {
diff --git a/jdk/src/share/classes/javax/swing/JComboBox.java b/jdk/src/share/classes/javax/swing/JComboBox.java
index 1074add..a5af753 100644
--- a/jdk/src/share/classes/javax/swing/JComboBox.java
+++ b/jdk/src/share/classes/javax/swing/JComboBox.java
@@ -1416,6 +1416,28 @@
}
/**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
+ if (super.processKeyBinding(ks, e, condition, pressed)) {
+ return true;
+ }
+
+ if (!isEditable() || condition != WHEN_FOCUSED || getEditor() == null
+ || !Boolean.TRUE.equals(getClientProperty("JComboBox.isTableCellEditor"))) {
+ return false;
+ }
+
+ Component editorComponent = getEditor().getEditorComponent();
+ if (editorComponent instanceof JComponent) {
+ JComponent component = (JComponent) editorComponent;
+ return component.processKeyBinding(ks, e, WHEN_FOCUSED, pressed);
+ }
+ return false;
+ }
+
+ /**
* Sets the object that translates a keyboard character into a list
* selection. Typically, the first selection with a matching first
* character becomes the selected item.
diff --git a/jdk/src/share/classes/javax/swing/text/html/EditableView.java b/jdk/src/share/classes/javax/swing/text/html/EditableView.java
index 3a5fa64..3ef2c65 100644
--- a/jdk/src/share/classes/javax/swing/text/html/EditableView.java
+++ b/jdk/src/share/classes/javax/swing/text/html/EditableView.java
@@ -73,7 +73,7 @@
Component c = getComponent();
Container host = getContainer();
- if (host != null &&
+ if (host instanceof JTextComponent &&
isVisible != ((JTextComponent)host).isEditable()) {
isVisible = ((JTextComponent)host).isEditable();
preferenceChanged(null, true, true);
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java
index 89eb6d4..98de323 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java
@@ -259,41 +259,68 @@
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else {
- int byteLength = i;
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- byteLength++;
- } else if (c > '\u07FF') {
- byteLength += 3;
- } else {
- byteLength += 2;
- }
- }
- if (byteLength > 65535) {
- throw new IllegalArgumentException();
- }
- data[length] = (byte) (byteLength >>> 8);
- data[length + 1] = (byte) byteLength;
- if (length + 2 + byteLength > data.length) {
- length = len;
- enlarge(2 + byteLength);
- data = this.data;
- }
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- data[len++] = (byte) c;
- } else if (c > '\u07FF') {
- data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
- data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- } else {
- data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- }
- }
- break;
+ length = len;
+ return encodeUTF8(s, i, 65535);
+ }
+ }
+ length = len;
+ return this;
+ }
+
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is
+ * automatically enlarged if necessary. The string length is encoded in two
+ * bytes before the encoded characters, if there is space for that (i.e. if
+ * this.length - i - 2 >= 0).
+ *
+ * @param s
+ * the String to encode.
+ * @param i
+ * the index of the first character to encode. The previous
+ * characters are supposed to have already been encoded, using
+ * only one byte per character.
+ * @param maxByteLength
+ * the maximum byte length of the encoded string, including the
+ * already encoded characters.
+ * @return this byte vector.
+ */
+ ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
+ int charLength = s.length();
+ int byteLength = i;
+ char c;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ byteLength++;
+ } else if (c > '\u07FF') {
+ byteLength += 3;
+ } else {
+ byteLength += 2;
+ }
+ }
+ if (byteLength > maxByteLength) {
+ throw new IllegalArgumentException();
+ }
+ int start = length - i - 2;
+ if (start >= 0) {
+ data[start] = (byte) (byteLength >>> 8);
+ data[start + 1] = (byte) byteLength;
+ }
+ if (length + byteLength - i > data.length) {
+ enlarge(byteLength - i);
+ }
+ int len = length;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else if (c > '\u07FF') {
+ data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+ data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ } else {
+ data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
}
}
length = len;
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
index ab9dcd0..66e8e7e 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
@@ -716,7 +716,8 @@
sourceFile = newUTF8(file);
}
if (debug != null) {
- sourceDebug = new ByteVector().putUTF8(debug);
+ sourceDebug = new ByteVector().encodeUTF8(debug, 0,
+ Integer.MAX_VALUE);
}
}
@@ -857,7 +858,7 @@
}
if (sourceDebug != null) {
++attributeCount;
- size += sourceDebug.length + 4;
+ size += sourceDebug.length + 6;
newUTF8("SourceDebugExtension");
}
if (enclosingMethodOwner != 0) {
@@ -946,9 +947,9 @@
out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
}
if (sourceDebug != null) {
- int len = sourceDebug.length - 2;
+ int len = sourceDebug.length;
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
- out.putByteArray(sourceDebug.data, 2, len);
+ out.putByteArray(sourceDebug.data, 0, len);
}
if (enclosingMethodOwner != 0) {
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java
index 78953ce..e32a13a 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java
@@ -99,8 +99,8 @@
* stack types. VALUE depends on KIND. For LOCAL types, it is an index in
* the input local variable types. For STACK types, it is a position
* relatively to the top of input frame stack. For BASE types, it is either
- * one of the constants defined in FrameVisitor, or for OBJECT and
- * UNINITIALIZED types, a tag and an index in the type table.
+ * one of the constants defined below, or for OBJECT and UNINITIALIZED
+ * types, a tag and an index in the type table.
*
* Output frames can contain types of any kind and with a positive or
* negative dimension (and even unassigned types, represented by 0 - which
@@ -537,7 +537,7 @@
/**
* The types that are initialized in the basic block. A constructor
* invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
- * <i>every occurrence</i> of this type in the local variables and in the
+ * <i>every occurence</i> of this type in the local variables and in the
* operand stack. This cannot be done during the first phase of the
* algorithm since, during this phase, the local variables and the operand
* stack are not completely computed. It is therefore necessary to store the
@@ -1446,6 +1446,7 @@
// if t is the NULL type, merge(u,t)=u, so there is no change
return false;
} else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+ // if t and u have the same dimension and same base kind
if ((u & BASE_KIND) == OBJECT) {
// if t is also a reference type, and if u and t have the
// same dimension merge(u,t) = dim(t) | common parent of the
@@ -1458,9 +1459,13 @@
v = OBJECT | cw.addType("java/lang/Object");
}
} else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
- // if t is any other reference or array type,
- // merge(u,t)=java/lang/Object
- v = OBJECT | cw.addType("java/lang/Object");
+ // if t is any other reference or array type, the merged type
+ // is Object, or min(dim(u), dim(t)) | java/lang/Object is u
+ // and t have different array dimensions
+ int tdim = t & DIM;
+ int udim = u & DIM;
+ v = (udim != tdim ? Math.min(tdim, udim) : 0) | OBJECT
+ | cw.addType("java/lang/Object");
} else {
// if t is any other type, merge(u,t)=TOP
v = TOP;
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java
index e914d45..b761bab 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java
@@ -240,6 +240,7 @@
locals.add(types[i].getInternalName());
}
}
+ maxLocals = locals.size();
}
@Override
@@ -519,12 +520,12 @@
// ------------------------------------------------------------------------
private Object get(final int local) {
- maxLocals = Math.max(maxLocals, local);
+ maxLocals = Math.max(maxLocals, local + 1);
return local < locals.size() ? locals.get(local) : Opcodes.TOP;
}
private void set(final int local, final Object type) {
- maxLocals = Math.max(maxLocals, local);
+ maxLocals = Math.max(maxLocals, local + 1);
while (local >= locals.size()) {
locals.add(Opcodes.TOP);
}
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java
index 2ba917c..7acfff5 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java
@@ -556,6 +556,8 @@
AbstractInsnNode prev;
+ AbstractInsnNode remove;
+
InsnListIterator(int index) {
if (index == size()) {
next = null;
@@ -577,12 +579,22 @@
AbstractInsnNode result = next;
prev = result;
next = result.next;
+ remove = result;
return result;
}
public void remove() {
- InsnList.this.remove(prev);
- prev = prev.prev;
+ if (remove != null) {
+ if (remove == next) {
+ next = next.next;
+ } else {
+ prev = prev.prev;
+ }
+ InsnList.this.remove(remove);
+ remove = null;
+ } else {
+ throw new IllegalStateException();
+ }
}
public boolean hasPrevious() {
@@ -593,6 +605,7 @@
AbstractInsnNode result = prev;
next = result;
prev = result.prev;
+ remove = result;
return result;
}
@@ -619,6 +632,7 @@
public void add(Object o) {
InsnList.this.insertBefore(next, (AbstractInsnNode) o);
prev = (AbstractInsnNode) o;
+ remove = null;
}
public void set(Object o) {
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java
index cd64b52..8f98753 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java
@@ -404,7 +404,7 @@
* instruction of the method. The size of the returned array is
* equal to the number of instructions (and labels) of the method. A
* given frame is <tt>null</tt> if the corresponding instruction
- * cannot be reached, or if an error occurred during the analysis of
+ * cannot be reached, or if an error occured during the analysis of
* the method.
*/
public Frame<V>[] getFrames() {
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java
index 122ee93..649d5a4 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java
@@ -111,7 +111,7 @@
* the bytecode instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occurred during the interpretation.
+ * if an error occured during the interpretation.
*/
public abstract V newOperation(AbstractInsnNode insn)
throws AnalyzerException;
@@ -130,7 +130,7 @@
* @return the result of the interpretation of the given instruction. The
* returned value must be <tt>equal</tt> to the given value.
* @throws AnalyzerException
- * if an error occurred during the interpretation.
+ * if an error occured during the interpretation.
*/
public abstract V copyOperation(AbstractInsnNode insn, V value)
throws AnalyzerException;
@@ -151,7 +151,7 @@
* the argument of the instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occurred during the interpretation.
+ * if an error occured during the interpretation.
*/
public abstract V unaryOperation(AbstractInsnNode insn, V value)
throws AnalyzerException;
@@ -175,7 +175,7 @@
* the second argument of the instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occurred during the interpretation.
+ * if an error occured during the interpretation.
*/
public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
throws AnalyzerException;
@@ -196,7 +196,7 @@
* the third argument of the instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occurred during the interpretation.
+ * if an error occured during the interpretation.
*/
public abstract V ternaryOperation(AbstractInsnNode insn, V value1,
V value2, V value3) throws AnalyzerException;
@@ -214,7 +214,7 @@
* the arguments of the instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occurred during the interpretation.
+ * if an error occured during the interpretation.
*/
public abstract V naryOperation(AbstractInsnNode insn,
List<? extends V> values) throws AnalyzerException;
@@ -232,7 +232,7 @@
* @param expected
* the expected return type of the analyzed method.
* @throws AnalyzerException
- * if an error occurred during the interpretation.
+ * if an error occured during the interpretation.
*/
public abstract void returnOperation(AbstractInsnNode insn, V value,
V expected) throws AnalyzerException;
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java
index 3650e37..4b68882 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java
@@ -99,7 +99,7 @@
}
if (value instanceof Type) {
int sort = ((Type) value).getSort();
- if (sort != Type.OBJECT && sort != Type.ARRAY) {
+ if (sort == Type.METHOD) {
throw new IllegalArgumentException("Invalid annotation value");
}
}
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java
index 5e20f52..5c2c8bf 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java
@@ -166,6 +166,11 @@
*/
protected Map<Label, String> labelNames;
+ /**
+ * Class access flags
+ */
+ private int access;
+
private int valueNumber = 0;
/**
@@ -245,6 +250,7 @@
public void visit(final int version, final int access, final String name,
final String signature, final String superName,
final String[] interfaces) {
+ this.access = access;
int major = version & 0xFFFF;
int minor = version >>> 16;
buf.setLength(0);
@@ -447,6 +453,11 @@
if ((access & Opcodes.ACC_BRIDGE) != 0) {
buf.append("bridge ");
}
+ if ((this.access & Opcodes.ACC_INTERFACE) != 0
+ && (access & Opcodes.ACC_ABSTRACT) == 0
+ && (access & Opcodes.ACC_STATIC) == 0) {
+ buf.append("default ");
+ }
buf.append(name);
appendDescriptor(METHOD_DESCRIPTOR, desc);
@@ -856,7 +867,6 @@
appendDescriptor(INTERNAL_NAME, owner);
buf.append('.').append(name).append(' ');
appendDescriptor(METHOD_DESCRIPTOR, desc);
- buf.append(' ').append(itf ? "itf" : "");
buf.append('\n');
text.add(buf.toString());
}
@@ -869,26 +879,35 @@
buf.append(name);
appendDescriptor(METHOD_DESCRIPTOR, desc);
buf.append(" [");
+ buf.append('\n');
+ buf.append(tab3);
appendHandle(bsm);
+ buf.append('\n');
buf.append(tab3).append("// arguments:");
if (bsmArgs.length == 0) {
buf.append(" none");
} else {
- buf.append('\n').append(tab3);
+ buf.append('\n');
for (int i = 0; i < bsmArgs.length; i++) {
+ buf.append(tab3);
Object cst = bsmArgs[i];
if (cst instanceof String) {
Printer.appendString(buf, (String) cst);
} else if (cst instanceof Type) {
- buf.append(((Type) cst).getDescriptor()).append(".class");
+ Type type = (Type) cst;
+ if(type.getSort() == Type.METHOD){
+ appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
+ } else {
+ buf.append(type.getDescriptor()).append(".class");
+ }
} else if (cst instanceof Handle) {
appendHandle((Handle) cst);
} else {
buf.append(cst);
}
- buf.append(", ");
+ buf.append(", \n");
}
- buf.setLength(buf.length() - 2);
+ buf.setLength(buf.length() - 3);
}
buf.append('\n');
buf.append(tab2).append("]\n");
@@ -1234,10 +1253,10 @@
* a handle, non null.
*/
protected void appendHandle(final Handle h) {
- buf.append('\n').append(tab3);
int tag = h.getTag();
buf.append("// handle kind 0x").append(Integer.toHexString(tag))
.append(" : ");
+ boolean isMethodHandle = false;
switch (tag) {
case Opcodes.H_GETFIELD:
buf.append("GETFIELD");
@@ -1253,18 +1272,23 @@
break;
case Opcodes.H_INVOKEINTERFACE:
buf.append("INVOKEINTERFACE");
+ isMethodHandle = true;
break;
case Opcodes.H_INVOKESPECIAL:
buf.append("INVOKESPECIAL");
+ isMethodHandle = true;
break;
case Opcodes.H_INVOKESTATIC:
buf.append("INVOKESTATIC");
+ isMethodHandle = true;
break;
case Opcodes.H_INVOKEVIRTUAL:
buf.append("INVOKEVIRTUAL");
+ isMethodHandle = true;
break;
case Opcodes.H_NEWINVOKESPECIAL:
buf.append("NEWINVOKESPECIAL");
+ isMethodHandle = true;
break;
}
buf.append('\n');
@@ -1272,9 +1296,13 @@
appendDescriptor(INTERNAL_NAME, h.getOwner());
buf.append('.');
buf.append(h.getName());
- buf.append('(');
+ if(!isMethodHandle){
+ buf.append('(');
+ }
appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
- buf.append(')').append('\n');
+ if(!isMethodHandle){
+ buf.append(')');
+ }
}
/**
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt
index efe71fa..c6f8ad6 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt
@@ -1,12 +1,12 @@
Path: .
-Working Copy Root Path: /hudson/jobs/objectweb-pull/workspace/ASM_5_0_BETA
-URL: svn://svn.forge.objectweb.org/svnroot/asm/trunk/asm
-Repository Root: svn://svn.forge.objectweb.org/svnroot/asm
+Working Copy Root Path: /hudson/jobs/objectweb-pull/workspace/asm-svn-2014-03-12
+URL: file:///svnroot/asm/trunk/asm
+Repository Root: file:///svnroot/asm
Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9
-Revision: 1700
+Revision: 1721
Node Kind: directory
Schedule: normal
Last Changed Author: ebruneton
-Last Changed Rev: 1700
-Last Changed Date: 2013-10-29 20:22:52 +0100 (Tue, 29 Oct 2013)
+Last Changed Rev: 1721
+Last Changed Date: 2014-03-02 17:25:35 +0100 (Sun, 02 Mar 2014)
diff --git a/jdk/src/share/classes/sun/awt/AppContext.java b/jdk/src/share/classes/sun/awt/AppContext.java
index c7f46ef..5959e54 100644
--- a/jdk/src/share/classes/sun/awt/AppContext.java
+++ b/jdk/src/share/classes/sun/awt/AppContext.java
@@ -42,11 +42,13 @@
import java.util.HashSet;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
+import java.lang.ref.SoftReference;
import sun.util.logging.PlatformLogger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
/**
* The AppContext is a table referenced by ThreadGroup which stores
@@ -883,6 +885,23 @@
});
}
+
+ public static <T> T getSoftReferenceValue(Object key,
+ Supplier<T> supplier) {
+
+ final AppContext appContext = AppContext.getAppContext();
+ SoftReference<T> ref = (SoftReference<T>) appContext.get(key);
+ if (ref != null) {
+ final T object = ref.get();
+ if (object != null) {
+ return object;
+ }
+ }
+ final T object = supplier.get();
+ ref = new SoftReference<>(object);
+ appContext.put(key, ref);
+ return object;
+ }
}
final class MostRecentKeyValue {
diff --git a/jdk/src/share/classes/sun/awt/image/ImageCache.java b/jdk/src/share/classes/sun/awt/image/ImageCache.java
new file mode 100644
index 0000000..c7088ba
--- /dev/null
+++ b/jdk/src/share/classes/sun/awt/image/ImageCache.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2011, 2014, 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.awt.image;
+
+import java.awt.*;
+import java.lang.ref.*;
+import java.util.*;
+import java.util.concurrent.locks.*;
+import sun.awt.AppContext;
+
+/**
+ * ImageCache - A fixed pixel count sized cache of Images keyed by arbitrary
+ * set of arguments. All images are held with SoftReferences so they will be
+ * dropped by the GC if heap memory gets tight. When our size hits max pixel
+ * count least recently requested images are removed first.
+ *
+ * The ImageCache must be used from the thread with an AppContext only.
+ *
+ */
+final public class ImageCache {
+
+ // Ordered Map keyed by args hash, ordered by most recent accessed entry.
+ private final LinkedHashMap<PixelsKey, ImageSoftReference> map
+ = new LinkedHashMap<>(16, 0.75f, true);
+
+ // Maximum number of pixels to cache, this is used if maxCount
+ private final int maxPixelCount;
+ // The current number of pixels stored in the cache
+ private int currentPixelCount = 0;
+
+ // Lock for concurrent access to map
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+ // Reference queue for tracking lost softreferences to images in the cache
+ private final ReferenceQueue<Image> referenceQueue = new ReferenceQueue<>();
+
+ public static ImageCache getInstance() {
+ return AppContext.getSoftReferenceValue(ImageCache.class,
+ () -> new ImageCache());
+ }
+
+ ImageCache(final int maxPixelCount) {
+ this.maxPixelCount = maxPixelCount;
+ }
+
+ ImageCache() {
+ this((8 * 1024 * 1024) / 4); // 8Mb of pixels
+ }
+
+ public void flush() {
+ lock.writeLock().lock();
+ try {
+ map.clear();
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public Image getImage(final PixelsKey key){
+ final ImageSoftReference ref;
+ lock.readLock().lock();
+ try {
+ ref = map.get(key);
+ } finally {
+ lock.readLock().unlock();
+ }
+ return ref == null ? null : ref.get();
+ }
+
+ /**
+ * Sets the cached image for the specified constraints.
+ *
+ * @param key The key with which the specified image is to be associated
+ * @param image The image to store in cache
+ */
+ public void setImage(final PixelsKey key, final Image image) {
+
+ lock.writeLock().lock();
+ try {
+ ImageSoftReference ref = map.get(key);
+
+ // check if currently in map
+ if (ref != null) {
+ if (ref.get() != null) {
+ return;
+ }
+ // soft image has been removed
+ currentPixelCount -= key.getPixelCount();
+ map.remove(key);
+ };
+
+
+ // add new image to pixel count
+ final int newPixelCount = key.getPixelCount();
+ currentPixelCount += newPixelCount;
+ // clean out lost references if not enough space
+ if (currentPixelCount > maxPixelCount) {
+ while ((ref = (ImageSoftReference)referenceQueue.poll()) != null) {
+ //reference lost
+ map.remove(ref.key);
+ currentPixelCount -= ref.key.getPixelCount();
+ }
+ }
+
+ // remove old items till there is enough free space
+ if (currentPixelCount > maxPixelCount) {
+ final Iterator<Map.Entry<PixelsKey, ImageSoftReference>>
+ mapIter = map.entrySet().iterator();
+ while ((currentPixelCount > maxPixelCount) && mapIter.hasNext()) {
+ final Map.Entry<PixelsKey, ImageSoftReference> entry =
+ mapIter.next();
+ mapIter.remove();
+ final Image img = entry.getValue().get();
+ if (img != null) img.flush();
+ currentPixelCount -= entry.getValue().key.getPixelCount();
+ }
+ }
+
+ // finally put new in map
+ map.put(key, new ImageSoftReference(key, image, referenceQueue));
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public interface PixelsKey {
+
+ int getPixelCount();
+ }
+
+ private static class ImageSoftReference extends SoftReference<Image> {
+
+ final PixelsKey key;
+
+ ImageSoftReference(final PixelsKey key, final Image referent,
+ final ReferenceQueue<? super Image> q) {
+ super(referent, q);
+ this.key = key;
+ }
+ }
+}
diff --git a/jdk/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java b/jdk/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java
index 79f7a3b..283095c 100644
--- a/jdk/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java
+++ b/jdk/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java
@@ -26,46 +26,152 @@
import java.awt.Image;
import java.awt.Graphics;
+import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
public class MultiResolutionBufferedImage extends BufferedImage
implements MultiResolutionImage {
- Image[] resolutionVariants;
- int baseIndex;
+ private final BiFunction<Integer, Integer, Image> mapper;
+ private final Dimension2D[] sizes;
+ private int availableInfo;
- public MultiResolutionBufferedImage(int imageType, int baseIndex, Image... images) {
- super(images[baseIndex].getWidth(null), images[baseIndex].getHeight(null),
- imageType);
- this.baseIndex = baseIndex;
- this.resolutionVariants = images;
+ public MultiResolutionBufferedImage(Image baseImage,
+ Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) {
+ super(baseImage.getWidth(null), baseImage.getHeight(null),
+ BufferedImage.TYPE_INT_ARGB_PRE);
+ this.sizes = sizes;
+ this.mapper = mapper;
+ this.availableInfo = getInfo(baseImage);
Graphics g = getGraphics();
- g.drawImage(images[baseIndex], 0, 0, null);
+ g.drawImage(baseImage, 0, 0, null);
g.dispose();
- images[baseIndex] = this;
}
@Override
public Image getResolutionVariant(int width, int height) {
- for (Image image : resolutionVariants) {
- if (width <= image.getWidth(null) && height <= image.getHeight(null)) {
- return image;
- }
+ int baseWidth = getWidth();
+ int baseHeight = getHeight();
+
+ if (baseWidth == width && baseHeight == height) {
+ return this;
}
- return this;
+
+ ImageCache cache = ImageCache.getInstance();
+ ImageCacheKey key = new ImageCacheKey(this, width, height);
+ Image resolutionVariant = cache.getImage(key);
+ if (resolutionVariant == null) {
+ resolutionVariant = mapper.apply(width, height);
+ cache.setImage(key, resolutionVariant);
+ preload(resolutionVariant, availableInfo);
+ }
+
+ return resolutionVariant;
}
@Override
public List<Image> getResolutionVariants() {
- return Arrays.asList(resolutionVariants);
+ return Arrays.stream(sizes).map((Function<Dimension2D, Image>) size
+ -> getResolutionVariant((int) size.getWidth(),
+ (int) size.getHeight())).collect(Collectors.toList());
}
public MultiResolutionBufferedImage map(Function<Image, Image> mapper) {
- return new MultiResolutionBufferedImage(getType(), baseIndex,
- Arrays.stream(resolutionVariants).map(mapper)
- .toArray(length -> new Image[length]));
+ return new MultiResolutionBufferedImage(mapper.apply(this), sizes,
+ (width, height) ->
+ mapper.apply(getResolutionVariant(width, height)));
}
-}
+
+ @Override
+ public int getWidth(ImageObserver observer) {
+ availableInfo |= ImageObserver.WIDTH;
+ return super.getWidth(observer);
+ }
+
+ @Override
+ public int getHeight(ImageObserver observer) {
+ availableInfo |= ImageObserver.HEIGHT;
+ return super.getHeight(observer);
+ }
+
+ @Override
+ public Object getProperty(String name, ImageObserver observer) {
+ availableInfo |= ImageObserver.PROPERTIES;
+ return super.getProperty(name, observer);
+ }
+
+ private static int getInfo(Image image) {
+ if (image instanceof ToolkitImage) {
+ return ((ToolkitImage) image).getImageRep().check(
+ (img, infoflags, x, y, w, h) -> false);
+ }
+ return 0;
+ }
+
+ private static void preload(Image image, int availableInfo) {
+ if (image instanceof ToolkitImage) {
+ ((ToolkitImage) image).preload(new ImageObserver() {
+ int flags = availableInfo;
+
+ @Override
+ public boolean imageUpdate(Image img, int infoflags,
+ int x, int y, int width, int height) {
+ flags &= ~infoflags;
+ return (flags != 0) && ((infoflags
+ & (ImageObserver.ERROR | ImageObserver.ABORT)) == 0);
+ }
+ });
+ }
+ }
+
+ private static class ImageCacheKey implements ImageCache.PixelsKey {
+
+ private final int pixelCount;
+ private final int hash;
+
+ private final int w;
+ private final int h;
+ private final Image baseImage;
+
+ ImageCacheKey(final Image baseImage,
+ final int w, final int h) {
+ this.baseImage = baseImage;
+ this.w = w;
+ this.h = h;
+ this.pixelCount = w * h;
+ hash = hash();
+ }
+
+ @Override
+ public int getPixelCount() {
+ return pixelCount;
+ }
+
+ private int hash() {
+ int hash = baseImage.hashCode();
+ hash = 31 * hash + w;
+ hash = 31 * hash + h;
+ return hash;
+ }
+
+ @Override
+ public int hashCode() {
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ImageCacheKey) {
+ ImageCacheKey key = (ImageCacheKey) obj;
+ return baseImage == key.baseImage && w == key.w && h == key.h;
+ }
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java
index bf0f13d..e3095fc 100644
--- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java
+++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java
@@ -443,20 +443,6 @@
return x;
}
- /**
- * Identity function, with reference cast.
- * @param t an arbitrary reference type
- * @param x an arbitrary reference value
- * @return the same value x
- */
- @SuppressWarnings("unchecked")
- static <T,U> T castReference(Class<? extends T> t, U x) {
- // inlined Class.cast because we can't ForceInline it
- if (x != null && !t.isInstance(x))
- throw newClassCastException(t, x);
- return (T) x;
- }
-
private static ClassCastException newClassCastException(Class<?> t, Object obj) {
return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
}
@@ -466,12 +452,10 @@
static {
try {
MethodType idType = MethodType.genericMethodType(1);
- MethodType castType = idType.insertParameterTypes(0, Class.class);
MethodType ignoreType = idType.changeReturnType(void.class);
MethodType zeroObjectType = MethodType.genericMethodType(0);
IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
- //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
- CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
+ CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
@@ -509,6 +493,9 @@
* and returns it as the given type.
*/
public static MethodHandle cast(Class<?> type) {
+ return cast(type, CAST_REFERENCE);
+ }
+ public static MethodHandle cast(Class<?> type, MethodHandle castReference) {
if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type);
MethodHandle mh;
Wrapper wrap = null;
@@ -519,7 +506,7 @@
mh = cache.get(wrap);
if (mh != null) return mh;
}
- mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
+ mh = MethodHandles.insertArguments(castReference, 0, type);
if (cache != null)
cache.put(wrap, mh);
return mh;
diff --git a/jdk/src/share/classes/sun/java2d/SunGraphics2D.java b/jdk/src/share/classes/sun/java2d/SunGraphics2D.java
index f66eee6..287549c 100644
--- a/jdk/src/share/classes/sun/java2d/SunGraphics2D.java
+++ b/jdk/src/share/classes/sun/java2d/SunGraphics2D.java
@@ -2430,6 +2430,8 @@
surfaceData = NullSurfaceData.theInstance;
}
+ invalidatePipe();
+
// this will recalculate the composite clip
setDevClip(surfaceData.getBounds());
diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
index 0c9bc24..9e2a49a 100644
--- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -31,6 +31,7 @@
import java.util.Base64;
import java.util.HashMap;
import sun.net.www.HeaderParser;
+import sun.util.logging.PlatformLogger;
import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
@@ -44,6 +45,7 @@
class NegotiateAuthentication extends AuthenticationInfo {
private static final long serialVersionUID = 100L;
+ private static final PlatformLogger logger = HttpURLConnection.getHttpLogger();
final private HttpCallerInfo hci;
@@ -79,6 +81,31 @@
}
/**
+ * Find out if the HttpCallerInfo supports Negotiate protocol.
+ * @return true if supported
+ */
+ public static boolean isSupported(HttpCallerInfo hci) {
+ ClassLoader loader = null;
+ try {
+ loader = Thread.currentThread().getContextClassLoader();
+ } catch (SecurityException se) {
+ if (logger.isLoggable(PlatformLogger.Level.FINER)) {
+ logger.finer("NegotiateAuthentication: " +
+ "Attempt to get the context class loader failed - " + se);
+ }
+ }
+
+ if (loader != null) {
+ // Lock on the class loader instance to avoid the deadlock engaging
+ // the lock in "ClassLoader.loadClass(String, boolean)" method.
+ synchronized (loader) {
+ return isSupportedImpl(hci);
+ }
+ }
+ return isSupportedImpl(hci);
+ }
+
+ /**
* Find out if the HttpCallerInfo supports Negotiate protocol. In order to
* find out yes or no, an initialization of a Negotiator object against it
* is tried. The generated object will be cached under the name of ths
@@ -89,7 +116,7 @@
*
* @return true if supported
*/
- synchronized public static boolean isSupported(HttpCallerInfo hci) {
+ private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) {
if (supported == null) {
supported = new HashMap <String, Boolean>();
cache = new HashMap <String, Negotiator>();
diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java
index a86cdfd..3b10862 100644
--- a/jdk/src/share/classes/sun/security/krb5/Config.java
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java
@@ -549,12 +549,11 @@
previous = line.substring(1).trim();
}
} else {
- if (previous == null) {
- throw new KrbException(
- "Config file must starts with a section");
+ // Lines before the first section are ignored
+ if (previous != null) {
+ v.add(previous);
+ previous = line;
}
- v.add(previous);
- previous = line;
}
}
if (previous != null) {
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
index c4eaff3..571801f 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
@@ -94,9 +94,6 @@
X509Certificate firstCert = certList.get(0);
// check trusted certificate's subject
selector.setSubject(firstCert.getIssuerX500Principal());
- // check the validity period
- selector.setValidityPeriod(firstCert.getNotBefore(),
- firstCert.getNotAfter());
/*
* Facilitate certification path construction with authority
* key identifier and subject key identifier.
diff --git a/jdk/src/share/classes/sun/security/x509/CRLReasonCodeExtension.java b/jdk/src/share/classes/sun/security/x509/CRLReasonCodeExtension.java
index 0016bc1..5212b0e 100644
--- a/jdk/src/share/classes/sun/security/x509/CRLReasonCodeExtension.java
+++ b/jdk/src/share/classes/sun/security/x509/CRLReasonCodeExtension.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -34,29 +34,9 @@
/**
* The reasonCode is a non-critical CRL entry extension that identifies
- * the reason for the certificate revocation. CAs are strongly
- * encouraged to include reason codes in CRL entries; however, the
- * reason code CRL entry extension should be absent instead of using the
- * unspecified (0) reasonCode value.
- * <p>The ASN.1 syntax for this is:
- * <pre>
- * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 }
- *
- * -- reasonCode ::= { CRLReason }
- *
- * CRLReason ::= ENUMERATED {
- * unspecified (0),
- * keyCompromise (1),
- * cACompromise (2),
- * affiliationChanged (3),
- * superseded (4),
- * cessationOfOperation (5),
- * certificateHold (6),
- * removeFromCRL (8),
- * privilegeWithdrawn (9),
- * aACompromise (10) }
- * </pre>
+ * the reason for the certificate revocation.
* @author Hemma Prafullchandra
+ * @see java.security.cert.CRLReason
* @see Extension
* @see CertAttrSet
*/
@@ -64,23 +44,11 @@
implements CertAttrSet<String> {
/**
- * Attribute name and Reason codes
+ * Attribute name
*/
public static final String NAME = "CRLReasonCode";
public static final String REASON = "reason";
- public static final int UNSPECIFIED = 0;
- public static final int KEY_COMPROMISE = 1;
- public static final int CA_COMPROMISE = 2;
- public static final int AFFLIATION_CHANGED = 3;
- public static final int SUPERSEDED = 4;
- public static final int CESSATION_OF_OPERATION = 5;
- public static final int CERTIFICATE_HOLD = 6;
- // note 7 missing in syntax
- public static final int REMOVE_FROM_CRL = 8;
- public static final int PRIVILEGE_WITHDRAWN = 9;
- public static final int AA_COMPROMISE = 10;
-
private static CRLReason[] values = CRLReason.values();
private int reasonCode = 0;
@@ -181,7 +149,7 @@
* Returns a printable representation of the Reason code.
*/
public String toString() {
- return super.toString() + " Reason Code: " + values[reasonCode];
+ return super.toString() + " Reason Code: " + getReasonCode();
}
/**
diff --git a/jdk/src/share/classes/sun/text/resources/es/FormatData_es_CL.java b/jdk/src/share/classes/sun/text/resources/es/FormatData_es_CL.java
index 87805df..49396af 100644
--- a/jdk/src/share/classes/sun/text/resources/es/FormatData_es_CL.java
+++ b/jdk/src/share/classes/sun/text/resources/es/FormatData_es_CL.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -57,10 +57,10 @@
},
{ "TimePatterns",
new String[] {
- "hh:mm:ss a z", // full time pattern
- "hh:mm:ss a z", // long time pattern
- "hh:mm:ss a", // medium time pattern
- "hh:mm a", // short time pattern
+ "HH:mm:ss zzzz", // full time pattern
+ "H:mm:ss z", // long time pattern
+ "H:mm:ss", // medium time pattern
+ "H:mm", // short time pattern
}
},
{ "DatePatterns",
diff --git a/jdk/src/share/classes/sun/text/resources/es/FormatData_es_EC.java b/jdk/src/share/classes/sun/text/resources/es/FormatData_es_EC.java
index a5283df..76ef82c 100644
--- a/jdk/src/share/classes/sun/text/resources/es/FormatData_es_EC.java
+++ b/jdk/src/share/classes/sun/text/resources/es/FormatData_es_EC.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -72,10 +72,10 @@
},
{ "TimePatterns",
new String[] {
- "hh:mm:ss a z", // full time pattern
- "hh:mm:ss a z", // long time pattern
- "hh:mm:ss a", // medium time pattern
- "hh:mm a", // short time pattern
+ "HH:mm:ss zzzz", // full time pattern
+ "H:mm:ss z", // long time pattern
+ "H:mm:ss", // medium time pattern
+ "H:mm", // short time pattern
}
},
{ "DatePatterns",
diff --git a/jdk/src/share/native/sun/font/FontInstanceAdapter.cpp b/jdk/src/share/native/sun/font/FontInstanceAdapter.cpp
index f2f553c..34fc4b2 100644
--- a/jdk/src/share/native/sun/font/FontInstanceAdapter.cpp
+++ b/jdk/src/share/native/sun/font/FontInstanceAdapter.cpp
@@ -222,10 +222,16 @@
jobject pt = env->NewObject(sunFontIDs.pt2DFloatClass,
sunFontIDs.pt2DFloatCtr,
adjustment.fX, adjustment.fY);
+ if (pt == NULL) {
+ env->ExceptionClear();
+ adjustment.fX = 0.0f;
+ adjustment.fY = 0.0f;
+ } else {
env->CallObjectMethod(fontStrike, sunFontIDs.adjustPointMID, pt);
adjustment.fX = env->GetFloatField(pt, sunFontIDs.xFID);
adjustment.fY = env->GetFloatField(pt, sunFontIDs.yFID);
}
+}
void FontInstanceAdapter::getWideGlyphAdvance(le_uint32 glyph, LEPoint &advance) const
{
diff --git a/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp b/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp
index 20618cd..ab65748 100644
--- a/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp
+++ b/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp
@@ -56,50 +56,13 @@
JNIEXPORT void JNICALL
Java_sun_font_SunLayoutEngine_initGVIDs
(JNIEnv *env, jclass cls) {
- gvdClass = env->FindClass(gvdClassName);
- if (!gvdClass) {
- JNU_ThrowClassNotFoundException(env, gvdClassName);
- return;
- }
- gvdClass = (jclass)env->NewGlobalRef(gvdClass);
- if (!gvdClass) {
- JNU_ThrowInternalError(env, "could not create global ref");
- return;
- }
- gvdCountFID = env->GetFieldID(gvdClass, "_count", "I");
- if (!gvdCountFID) {
- gvdClass = 0;
- JNU_ThrowNoSuchFieldException(env, "_count");
- return;
- }
-
- gvdFlagsFID = env->GetFieldID(gvdClass, "_flags", "I");
- if (!gvdFlagsFID) {
- gvdClass = 0;
- JNU_ThrowNoSuchFieldException(env, "_flags");
- return;
- }
-
- gvdGlyphsFID = env->GetFieldID(gvdClass, "_glyphs", "[I");
- if (!gvdGlyphsFID) {
- gvdClass = 0;
- JNU_ThrowNoSuchFieldException(env, "_glyphs");
- return;
- }
-
- gvdPositionsFID = env->GetFieldID(gvdClass, "_positions", "[F");
- if (!gvdPositionsFID) {
- gvdClass = 0;
- JNU_ThrowNoSuchFieldException(env, "_positions");
- return;
- }
-
+ CHECK_NULL(gvdClass = env->FindClass(gvdClassName));
+ CHECK_NULL(gvdClass = (jclass)env->NewGlobalRef(gvdClass));
+ CHECK_NULL(gvdCountFID = env->GetFieldID(gvdClass, "_count", "I"));
+ CHECK_NULL(gvdFlagsFID = env->GetFieldID(gvdClass, "_flags", "I"));
+ CHECK_NULL(gvdGlyphsFID = env->GetFieldID(gvdClass, "_glyphs", "[I"));
+ CHECK_NULL(gvdPositionsFID = env->GetFieldID(gvdClass, "_positions", "[F"));
gvdIndicesFID = env->GetFieldID(gvdClass, "_indices", "[I");
- if (!gvdIndicesFID) {
- gvdClass = 0;
- JNU_ThrowNoSuchFieldException(env, "_indices");
- return;
- }
}
int putGV(JNIEnv* env, jint gmask, jint baseIndex, jobject gvdata, const LayoutEngine* engine, int glyphCount) {
@@ -195,7 +158,7 @@
jchar* chars = buffer;
if (len > 256) {
size_t size = len * sizeof(jchar);
- if (size / sizeof(jchar) != len) {
+ if (size / sizeof(jchar) != (size_t)len) {
return;
}
chars = (jchar*)malloc(size);
@@ -220,10 +183,12 @@
env->SetIntField(gvdata, gvdCountFID, -1); // flag failure
} else {
if (putGV(env, gmask, baseIndex, gvdata, engine, glyphCount)) {
+ if (!(env->ExceptionCheck())) {
// !!! hmmm, could use current value in positions array of GVData...
putFloat(env, pt, x, y);
}
}
+ }
if (chars != buffer) {
free(chars);
diff --git a/jdk/src/share/native/sun/font/sunFont.c b/jdk/src/share/native/sun/font/sunFont.c
index 50a62e4..294328b 100644
--- a/jdk/src/share/native/sun/font/sunFont.c
+++ b/jdk/src/share/native/sun/font/sunFont.c
@@ -27,6 +27,7 @@
#include "string.h"
#include "gdefs.h"
#include "jlong.h"
+#include "jni_util.h"
#include "sunfontids.h"
#include "fontscalerdefs.h"
#include "sun_font_SunFontManager.h"
@@ -81,100 +82,106 @@
if (initialisedFontIDs) {
return;
}
- tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont");
- sunFontIDs.ttReadBlockMID =
+ CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont"));
+ CHECK_NULL(sunFontIDs.ttReadBlockMID =
(*env)->GetMethodID(env, tmpClass, "readBlock",
- "(Ljava/nio/ByteBuffer;II)I");
- sunFontIDs.ttReadBytesMID =
- (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B");
+ "(Ljava/nio/ByteBuffer;II)I"));
+ CHECK_NULL(sunFontIDs.ttReadBytesMID =
+ (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B"));
- tmpClass = (*env)->FindClass(env, "sun/font/Type1Font");
- sunFontIDs.readFileMID =
+ CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Type1Font"));
+ CHECK_NULL(sunFontIDs.readFileMID =
(*env)->GetMethodID(env, tmpClass,
- "readFile", "(Ljava/nio/ByteBuffer;)V");
+ "readFile", "(Ljava/nio/ByteBuffer;)V"));
- tmpClass = (*env)->FindClass(env, "java/awt/geom/Point2D$Float");
+ CHECK_NULL(tmpClass =
+ (*env)->FindClass(env, "java/awt/geom/Point2D$Float"));
sunFontIDs.pt2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
- sunFontIDs.pt2DFloatCtr =
- (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V");
+ CHECK_NULL(sunFontIDs.pt2DFloatCtr =
+ (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V"));
- sunFontIDs.xFID =
- (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F");
- sunFontIDs.yFID =
- (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F");
+ CHECK_NULL(sunFontIDs.xFID =
+ (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F"));
+ CHECK_NULL(sunFontIDs.yFID =
+ (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F"));
- tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics");
- sunFontIDs.strikeMetricsClass=(jclass)(*env)->NewGlobalRef(env, tmpClass);
+ CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics"));
+ CHECK_NULL(sunFontIDs.strikeMetricsClass =
+ (jclass)(*env)->NewGlobalRef(env, tmpClass));
- sunFontIDs.strikeMetricsCtr =
+ CHECK_NULL(sunFontIDs.strikeMetricsCtr =
(*env)->GetMethodID(env, sunFontIDs.strikeMetricsClass,
- "<init>", "(FFFFFFFFFF)V");
+ "<init>", "(FFFFFFFFFF)V"));
- tmpClass = (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float");
+ CHECK_NULL(tmpClass =
+ (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float"));
sunFontIDs.rect2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
- sunFontIDs.rect2DFloatCtr =
- (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V");
- sunFontIDs.rect2DFloatCtr4 =
+ CHECK_NULL(sunFontIDs.rect2DFloatCtr =
+ (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V"));
+ CHECK_NULL(sunFontIDs.rect2DFloatCtr4 =
(*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass,
- "<init>", "(FFFF)V");
- sunFontIDs.rectF2DX =
- (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F");
- sunFontIDs.rectF2DY =
- (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F");
- sunFontIDs.rectF2DWidth =
- (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F");
- sunFontIDs.rectF2DHeight =
- (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F");
+ "<init>", "(FFFF)V"));
+ CHECK_NULL(sunFontIDs.rectF2DX =
+ (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F"));
+ CHECK_NULL(sunFontIDs.rectF2DY =
+ (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F"));
+ CHECK_NULL(sunFontIDs.rectF2DWidth =
+ (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F"));
+ CHECK_NULL(sunFontIDs.rectF2DHeight =
+ (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F"));
- tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath");
+ CHECK_NULL(tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath"));
sunFontIDs.gpClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
- sunFontIDs.gpCtr =
- (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V");
- sunFontIDs.gpCtrEmpty =
- (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V");
+ CHECK_NULL(sunFontIDs.gpCtr =
+ (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V"));
+ CHECK_NULL(sunFontIDs.gpCtrEmpty =
+ (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V"));
- tmpClass = (*env)->FindClass(env, "sun/font/Font2D");
- sunFontIDs.f2dCharToGlyphMID =
- (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I");
- sunFontIDs.getMapperMID =
+ CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Font2D"));
+ CHECK_NULL(sunFontIDs.f2dCharToGlyphMID =
+ (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I"));
+ CHECK_NULL(sunFontIDs.getMapperMID =
(*env)->GetMethodID(env, tmpClass, "getMapper",
- "()Lsun/font/CharToGlyphMapper;");
- sunFontIDs.getTableBytesMID =
- (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B");
- sunFontIDs.canDisplayMID =
- (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z");
+ "()Lsun/font/CharToGlyphMapper;"));
+ CHECK_NULL(sunFontIDs.getTableBytesMID =
+ (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B"));
+ CHECK_NULL(sunFontIDs.canDisplayMID =
+ (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z"));
- tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper");
- sunFontIDs.charToGlyphMID =
- (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I");
+ CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper"));
+ CHECK_NULL(sunFontIDs.charToGlyphMID =
+ (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I"));
- tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike");
- sunFontIDs.getGlyphMetricsMID =
+ CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike"));
+ CHECK_NULL(sunFontIDs.getGlyphMetricsMID =
(*env)->GetMethodID(env, tmpClass, "getGlyphMetrics",
- "(I)Ljava/awt/geom/Point2D$Float;");
- sunFontIDs.getGlyphPointMID =
+ "(I)Ljava/awt/geom/Point2D$Float;"));
+ CHECK_NULL(sunFontIDs.getGlyphPointMID =
(*env)->GetMethodID(env, tmpClass, "getGlyphPoint",
- "(II)Ljava/awt/geom/Point2D$Float;");
- sunFontIDs.adjustPointMID =
+ "(II)Ljava/awt/geom/Point2D$Float;"));
+ CHECK_NULL(sunFontIDs.adjustPointMID =
(*env)->GetMethodID(env, tmpClass, "adjustPoint",
- "(Ljava/awt/geom/Point2D$Float;)V");
- sunFontIDs.pScalerContextFID =
- (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J");
+ "(Ljava/awt/geom/Point2D$Float;)V"));
+ CHECK_NULL(sunFontIDs.pScalerContextFID =
+ (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J"));
- tmpClass = (*env)->FindClass(env, "sun/font/GlyphList");
- sunFontIDs.glyphListX = (*env)->GetFieldID(env, tmpClass, "x", "F");
- sunFontIDs.glyphListY = (*env)->GetFieldID(env, tmpClass, "y", "F");
- sunFontIDs.glyphListLen = (*env)->GetFieldID(env, tmpClass, "len", "I");
- sunFontIDs.glyphImages =
- (*env)->GetFieldID(env, tmpClass, "images", "[J");
- sunFontIDs.glyphListUsePos =
- (*env)->GetFieldID(env, tmpClass, "usePositions", "Z");
- sunFontIDs.glyphListPos =
- (*env)->GetFieldID(env, tmpClass, "positions", "[F");
- sunFontIDs.lcdRGBOrder =
- (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z");
- sunFontIDs.lcdSubPixPos =
- (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z");
+ CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/GlyphList"));
+ CHECK_NULL(sunFontIDs.glyphListX =
+ (*env)->GetFieldID(env, tmpClass, "x", "F"));
+ CHECK_NULL(sunFontIDs.glyphListY =
+ (*env)->GetFieldID(env, tmpClass, "y", "F"));
+ CHECK_NULL(sunFontIDs.glyphListLen =
+ (*env)->GetFieldID(env, tmpClass, "len", "I"));
+ CHECK_NULL(sunFontIDs.glyphImages =
+ (*env)->GetFieldID(env, tmpClass, "images", "[J"));
+ CHECK_NULL(sunFontIDs.glyphListUsePos =
+ (*env)->GetFieldID(env, tmpClass, "usePositions", "Z"));
+ CHECK_NULL(sunFontIDs.glyphListPos =
+ (*env)->GetFieldID(env, tmpClass, "positions", "[F"));
+ CHECK_NULL(sunFontIDs.lcdRGBOrder =
+ (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z"));
+ CHECK_NULL(sunFontIDs.lcdSubPixPos =
+ (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z"));
initLCDGammaTables();
diff --git a/jdk/src/share/native/sun/security/pkcs11/j2secmod.c b/jdk/src/share/native/sun/security/pkcs11/j2secmod.c
index 9c648fa..4ed2f15 100644
--- a/jdk/src/share/native/sun/security/pkcs11/j2secmod.c
+++ b/jdk/src/share/native/sun/security/pkcs11/j2secmod.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -30,20 +30,27 @@
// #define SECMOD_DEBUG
#include "j2secmod.h"
+#include "jni_util.h"
JNIEXPORT jboolean JNICALL Java_sun_security_pkcs11_Secmod_nssVersionCheck
(JNIEnv *env, jclass thisClass, jlong jHandle, jstring jVersion)
{
- const char *requiredVersion = (*env)->GetStringUTFChars(env, jVersion, NULL);
- int res;
- FPTR_VersionCheck versionCheck =
- (FPTR_VersionCheck)findFunction(env, jHandle, "NSS_VersionCheck");
+ int res = 0;
+ FPTR_VersionCheck versionCheck;
+ const char *requiredVersion;
+ versionCheck = (FPTR_VersionCheck)findFunction(env, jHandle,
+ "NSS_VersionCheck");
if (versionCheck == NULL) {
return JNI_FALSE;
}
+ requiredVersion = (*env)->GetStringUTFChars(env, jVersion, NULL);
+ if (requiredVersion == NULL) {
+ return JNI_FALSE;
+ }
+
res = versionCheck(requiredVersion);
dprintf2("-version >=%s: %d\n", requiredVersion, res);
(*env)->ReleaseStringUTFChars(env, jVersion, requiredVersion);
@@ -59,55 +66,73 @@
JNIEXPORT jboolean JNICALL Java_sun_security_pkcs11_Secmod_nssInitialize
(JNIEnv *env, jclass thisClass, jstring jFunctionName, jlong jHandle, jstring jConfigDir, jboolean jNssOptimizeSpace)
{
- const char *functionName =
- (*env)->GetStringUTFChars(env, jFunctionName, NULL);
- const char *configDir = (jConfigDir == NULL)
- ? NULL : (*env)->GetStringUTFChars(env, jConfigDir, NULL);
+ int res = 0;
FPTR_Initialize initialize =
(FPTR_Initialize)findFunction(env, jHandle, "NSS_Initialize");
- int res = 0;
unsigned int flags = 0x00;
+ const char *configDir = NULL;
+ const char *functionName = NULL;
+
+ /* If we cannot initialize, exit now */
+ if (initialize == NULL) {
+ res = 1;
+ goto cleanup;
+ }
+
+ functionName = (*env)->GetStringUTFChars(env, jFunctionName, NULL);
+ if (functionName == NULL) {
+ res = 1;
+ goto cleanup;
+ }
+
+ if (jConfigDir != NULL) {
+ configDir = (*env)->GetStringUTFChars(env, jConfigDir, NULL);
+ if (!configDir) {
+ res = 1;
+ goto cleanup;
+ }
+ }
if (jNssOptimizeSpace == JNI_TRUE) {
flags = 0x20; // NSS_INIT_OPTIMIZESPACE flag
}
- if (initialize != NULL) {
- /*
- * If the NSS_Init function is requested then call NSS_Initialize to
- * open the Cert, Key and Security Module databases, read only.
- */
- if (strcmp("NSS_Init", functionName) == 0) {
- flags = flags | 0x01; // NSS_INIT_READONLY flag
- res = initialize(configDir, "", "", "secmod.db", flags);
+ /*
+ * If the NSS_Init function is requested then call NSS_Initialize to
+ * open the Cert, Key and Security Module databases, read only.
+ */
+ if (strcmp("NSS_Init", functionName) == 0) {
+ flags = flags | 0x01; // NSS_INIT_READONLY flag
+ res = initialize(configDir, "", "", "secmod.db", flags);
- /*
- * If the NSS_InitReadWrite function is requested then call
- * NSS_Initialize to open the Cert, Key and Security Module databases,
- * read/write.
- */
- } else if (strcmp("NSS_InitReadWrite", functionName) == 0) {
- res = initialize(configDir, "", "", "secmod.db", flags);
+ /*
+ * If the NSS_InitReadWrite function is requested then call
+ * NSS_Initialize to open the Cert, Key and Security Module databases,
+ * read/write.
+ */
+ } else if (strcmp("NSS_InitReadWrite", functionName) == 0) {
+ res = initialize(configDir, "", "", "secmod.db", flags);
- /*
- * If the NSS_NoDB_Init function is requested then call
- * NSS_Initialize without creating Cert, Key or Security Module
- * databases.
- */
- } else if (strcmp("NSS_NoDB_Init", functionName) == 0) {
- flags = flags | 0x02 // NSS_INIT_NOCERTDB flag
- | 0x04 // NSS_INIT_NOMODDB flag
- | 0x08 // NSS_INIT_FORCEOPEN flag
- | 0x10; // NSS_INIT_NOROOTINIT flag
- res = initialize("", "", "", "", flags);
+ /*
+ * If the NSS_NoDB_Init function is requested then call
+ * NSS_Initialize without creating Cert, Key or Security Module
+ * databases.
+ */
+ } else if (strcmp("NSS_NoDB_Init", functionName) == 0) {
+ flags = flags | 0x02 // NSS_INIT_NOCERTDB flag
+ | 0x04 // NSS_INIT_NOMODDB flag
+ | 0x08 // NSS_INIT_FORCEOPEN flag
+ | 0x10; // NSS_INIT_NOROOTINIT flag
+ res = initialize("", "", "", "", flags);
- } else {
- res = 2;
- }
} else {
- res = 1;
+ res = 2;
}
- (*env)->ReleaseStringUTFChars(env, jFunctionName, functionName);
+
+cleanup:
+ if (functionName != NULL) {
+ (*env)->ReleaseStringUTFChars(env, jFunctionName, functionName);
+ }
if (configDir != NULL) {
(*env)->ReleaseStringUTFChars(env, jConfigDir, configDir);
}
@@ -142,13 +167,30 @@
}
jListClass = (*env)->FindClass(env, "java/util/ArrayList");
+ if (jListClass == NULL) {
+ return NULL;
+ }
jListConstructor = (*env)->GetMethodID(env, jListClass, "<init>", "()V");
+ if (jListConstructor == NULL) {
+ return NULL;
+ }
jAdd = (*env)->GetMethodID(env, jListClass, "add", "(Ljava/lang/Object;)Z");
+ if (jAdd == NULL) {
+ return NULL;
+ }
jList = (*env)->NewObject(env, jListClass, jListConstructor);
-
+ if (jList == NULL) {
+ return NULL;
+ }
jModuleClass = (*env)->FindClass(env, "sun/security/pkcs11/Secmod$Module");
+ if (jModuleClass == NULL) {
+ return NULL;
+ }
jModuleConstructor = (*env)->GetMethodID(env, jModuleClass, "<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)V");
+ if (jModuleConstructor == NULL) {
+ return NULL;
+ }
while (list != NULL) {
module = list->module;
@@ -160,16 +202,28 @@
dprintf1("-internal: %d\n", module->internal);
dprintf1("-fips: %d\n", module->isFIPS);
jCommonName = (*env)->NewStringUTF(env, module->commonName);
+ if (jCommonName == NULL) {
+ return NULL;
+ }
if (module->dllName == NULL) {
jDllName = NULL;
} else {
jDllName = (*env)->NewStringUTF(env, module->dllName);
+ if (jDllName == NULL) {
+ return NULL;
+ }
}
jFIPS = module->isFIPS;
for (i = 0; i < module->slotCount; i++ ) {
jModule = (*env)->NewObject(env, jModuleClass, jModuleConstructor,
jLibDir, jDllName, jCommonName, jFIPS, i);
+ if (jModule == NULL) {
+ return NULL;
+ }
(*env)->CallVoidMethod(env, jList, jAdd, jModule);
+ if ((*env)->ExceptionCheck(env)) {
+ return NULL;
+ }
}
list = list->next;
}
diff --git a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.bsd b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.bsd
index f47fcd1..8f2069e 100644
--- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.bsd
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.bsd
@@ -342,47 +342,39 @@
ProcessPipeInputStream(int fd) {
super(new FileInputStream(newFileDescriptor(fd)));
}
-
- private InputStream drainInputStream(InputStream in)
+ private static byte[] drainInputStream(InputStream in)
throws IOException {
int n = 0;
int j;
byte[] a = null;
- synchronized (closeLock) {
- if (buf == null) // asynchronous close()?
- return null; // discard
- j = in.available();
- }
- while (j > 0) {
+ while ((j = in.available()) > 0) {
a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
- synchronized (closeLock) {
- if (buf == null) // asynchronous close()?
- return null; // discard
- n += in.read(a, n, j);
- j = in.available();
- }
+ n += in.read(a, n, j);
}
- return (a == null) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
+ return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
}
/** Called by the process reaper thread when the process exits. */
synchronized void processExited() {
- try {
- InputStream in = this.in;
- if (in != null) {
- InputStream stragglers = drainInputStream(in);
- in.close();
- this.in = stragglers;
- }
- } catch (IOException ignored) { }
+ synchronized (closeLock) {
+ try {
+ InputStream in = this.in;
+ // this stream is closed if and only if: in == null
+ if (in != null) {
+ byte[] stragglers = drainInputStream(in);
+ in.close();
+ this.in = (stragglers == null) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ByteArrayInputStream(stragglers);
+ }
+ } catch (IOException ignored) {}
+ }
}
@Override
public void close() throws IOException {
// BufferedInputStream#close() is not synchronized unlike most other methods.
- // Synchronizing helps avoid racing with drainInputStream().
+ // Synchronizing helps avoid race with processExited().
synchronized (closeLock) {
super.close();
}
diff --git a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux
index 7c7dbe6..3357495 100644
--- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux
@@ -344,47 +344,39 @@
ProcessPipeInputStream(int fd) {
super(new FileInputStream(newFileDescriptor(fd)));
}
-
- private InputStream drainInputStream(InputStream in)
+ private static byte[] drainInputStream(InputStream in)
throws IOException {
int n = 0;
int j;
byte[] a = null;
- synchronized (closeLock) {
- if (buf == null) // asynchronous close()?
- return null; // discard
- j = in.available();
- }
- while (j > 0) {
+ while ((j = in.available()) > 0) {
a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
- synchronized (closeLock) {
- if (buf == null) // asynchronous close()?
- return null; // discard
- n += in.read(a, n, j);
- j = in.available();
- }
+ n += in.read(a, n, j);
}
- return (a == null) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
+ return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
}
/** Called by the process reaper thread when the process exits. */
synchronized void processExited() {
- try {
- InputStream in = this.in;
- if (in != null) {
- InputStream stragglers = drainInputStream(in);
- in.close();
- this.in = stragglers;
- }
- } catch (IOException ignored) { }
+ synchronized (closeLock) {
+ try {
+ InputStream in = this.in;
+ // this stream is closed if and only if: in == null
+ if (in != null) {
+ byte[] stragglers = drainInputStream(in);
+ in.close();
+ this.in = (stragglers == null) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ByteArrayInputStream(stragglers);
+ }
+ } catch (IOException ignored) {}
+ }
}
@Override
public void close() throws IOException {
// BufferedInputStream#close() is not synchronized unlike most other methods.
- // Synchronizing helps avoid racing with drainInputStream().
+ // Synchronizing helps avoid race with processExited().
synchronized (closeLock) {
super.close();
}
diff --git a/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c
index 225556b..2ccf0f8 100644
--- a/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c
+++ b/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c
@@ -38,8 +38,7 @@
#include "sun_nio_ch_sctp_ResultContainer.h"
#include "sun_nio_ch_sctp_PeerAddrChange.h"
-/* sizeof(union sctp_notification */
-#define NOTIFICATION_BUFFER_SIZE 280
+static int SCTP_NOTIFICATION_SIZE = sizeof(union sctp_notification);
#define MESSAGE_IMPL_CLASS "sun/nio/ch/sctp/MessageInfoImpl"
#define RESULT_CONTAINER_CLASS "sun/nio/ch/sctp/ResultContainer"
@@ -460,20 +459,47 @@
if (msg->msg_flags & MSG_NOTIFICATION) {
char *bufp = (char*)addr;
union sctp_notification *snp;
+ jboolean allocated = JNI_FALSE;
- if (!(msg->msg_flags & MSG_EOR) && length < NOTIFICATION_BUFFER_SIZE) {
- char buf[NOTIFICATION_BUFFER_SIZE];
+ if (rv > SCTP_NOTIFICATION_SIZE) {
+ JNU_ThrowInternalError(env, "should not reach here");
+ return -1;
+ }
+
+ if (!(msg->msg_flags & MSG_EOR) && length < SCTP_NOTIFICATION_SIZE) {
+ char* newBuf;
int rvSAVE = rv;
- memcpy(buf, addr, rv);
- iov->iov_base = buf + rv;
- iov->iov_len = NOTIFICATION_BUFFER_SIZE - rv;
+
+ if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "Out of native heap space.");
+ return -1;
+ }
+ allocated = JNI_TRUE;
+
+ memcpy(newBuf, addr, rv);
+ iov->iov_base = newBuf + rv;
+ iov->iov_len = SCTP_NOTIFICATION_SIZE - rv;
if ((rv = recvmsg(fd, msg, flags)) < 0) {
handleSocketError(env, errno);
return 0;
}
- bufp = buf;
+ bufp = newBuf;
rv += rvSAVE;
}
+#ifdef __sparc
+ else if ((intptr_t)addr & 0x3) {
+ /* the given buffer is not 4 byte aligned */
+ char* newBuf;
+ if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "Out of native heap space.");
+ return -1;
+ }
+ allocated = JNI_TRUE;
+
+ memcpy(newBuf, addr, rv);
+ bufp = newBuf;
+ }
+#endif
snp = (union sctp_notification *) bufp;
if (handleNotification(env, fd, resultContainerObj, snp, rv,
(msg->msg_flags & MSG_EOR),
@@ -481,9 +507,16 @@
/* We have received a notification that is of interest to
to the Java API. The appropriate notification will be
set in the result container. */
+ if (allocated == JNI_TRUE) {
+ free(bufp);
+ }
return 0;
}
+ if (allocated == JNI_TRUE) {
+ free(bufp);
+ }
+
// set iov back to addr, and reset msg_controllen
iov->iov_base = addr;
iov->iov_len = length;
diff --git a/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c b/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c
index 8b3a62b..0b89f11 100644
--- a/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c
+++ b/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -49,6 +49,10 @@
(JNIEnv *env, jclass thisClass, jstring jLibName)
{
const char *libName = (*env)->GetStringUTFChars(env, jLibName, NULL);
+ if (libName == NULL) {
+ return 0L;
+ }
+
// look up existing handle only, do not load
#if defined(AIX)
void *hModule = dlopen(libName, RTLD_LAZY);
@@ -65,6 +69,9 @@
{
void *hModule;
const char *libName = (*env)->GetStringUTFChars(env, jLibName, NULL);
+ if (libName == NULL) {
+ return 0L;
+ }
dprintf1("-lib %s\n", libName);
hModule = dlopen(libName, RTLD_LAZY);
diff --git a/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c b/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c
index 3d805c5..fe05a1d 100644
--- a/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c
+++ b/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
@@ -88,6 +88,9 @@
const char *getFunctionListStr;
const char *libraryNameStr = (*env)->GetStringUTFChars(env, jPkcs11ModulePath, 0);
+ if (libraryNameStr == NULL) {
+ return;
+ }
TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr);
@@ -123,6 +126,9 @@
// with the old JAR file jGetFunctionList is null, temporarily check for that
if (jGetFunctionList != NULL) {
getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0);
+ if (getFunctionListStr == NULL) {
+ return;
+ }
C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr);
(*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr);
}
diff --git a/jdk/src/windows/native/sun/windows/MouseInfo.cpp b/jdk/src/windows/native/sun/windows/MouseInfo.cpp
index 4878fa2..b109f28 100644
--- a/jdk/src/windows/native/sun/windows/MouseInfo.cpp
+++ b/jdk/src/windows/native/sun/windows/MouseInfo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -95,7 +95,9 @@
env->DeleteLocalRef(pointClassLocal);
}
xID = env->GetFieldID(pointClass, "x", "I");
+ CHECK_NULL_RETURN(xID, (jint)0);
yID = env->GetFieldID(pointClass, "y", "I");
+ CHECK_NULL_RETURN(yID, (jint)0);
env->SetIntField(point, xID, pt.x);
env->SetIntField(point, yID, pt.y);
diff --git a/jdk/src/windows/native/sun/windows/awt.h b/jdk/src/windows/native/sun/windows/awt.h
index 060953c..5ce4d22 100644
--- a/jdk/src/windows/native/sun/windows/awt.h
+++ b/jdk/src/windows/native/sun/windows/awt.h
@@ -49,6 +49,7 @@
#define JNI_CHECK_NULL_GOTO(obj, msg, where) { \
if (obj == NULL) { \
+ env->ExceptionClear(); \
JNU_ThrowNullPointerException(env, msg); \
goto where; \
} \
@@ -65,6 +66,7 @@
#define JNI_CHECK_NULL_RETURN(obj, msg) { \
if (obj == NULL) { \
+ env->ExceptionClear(); \
JNU_ThrowNullPointerException(env, msg); \
return; \
} \
@@ -91,6 +93,7 @@
#define JNI_CHECK_NULL_RETURN_NULL(obj, msg) { \
if (obj == NULL) { \
+ env->ExceptionClear(); \
JNU_ThrowNullPointerException(env, msg); \
return 0; \
} \
@@ -98,6 +101,7 @@
#define JNI_CHECK_NULL_RETURN_VAL(obj, msg, val) { \
if (obj == NULL) { \
+ env->ExceptionClear(); \
JNU_ThrowNullPointerException(env, msg); \
return val; \
} \
@@ -124,6 +128,7 @@
#define THROW_NULL_PDATA_IF_NOT_DESTROYED(peer) { \
jboolean destroyed = JNI_GET_DESTROYED(peer); \
if (destroyed != JNI_TRUE) { \
+ env->ExceptionClear(); \
JNU_ThrowNullPointerException(env, "null pData"); \
} \
}
diff --git a/jdk/src/windows/native/sun/windows/awt_AWTEvent.cpp b/jdk/src/windows/native/sun/windows/awt_AWTEvent.cpp
index c6bd697..c1c17f9 100644
--- a/jdk/src/windows/native/sun/windows/awt_AWTEvent.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_AWTEvent.cpp
@@ -71,12 +71,16 @@
TRY;
AwtAWTEvent::bdataID = env->GetFieldID(cls, "bdata", "[B");
- AwtAWTEvent::idID = env->GetFieldID(cls, "id", "I");
- AwtAWTEvent::consumedID = env->GetFieldID(cls, "consumed", "Z");
-
DASSERT(AwtAWTEvent::bdataID != NULL);
+ CHECK_NULL(AwtAWTEvent::bdataID);
+
+ AwtAWTEvent::idID = env->GetFieldID(cls, "id", "I");
DASSERT(AwtAWTEvent::idID != NULL);
+ CHECK_NULL(AwtAWTEvent::idID);
+
+ AwtAWTEvent::consumedID = env->GetFieldID(cls, "consumed", "Z");
DASSERT(AwtAWTEvent::consumedID != NULL);
+ CHECK_NULL(AwtAWTEvent::consumedID);
CATCH_BAD_ALLOC;
}
diff --git a/jdk/src/windows/native/sun/windows/awt_Component.cpp b/jdk/src/windows/native/sun/windows/awt_Component.cpp
index 345e9f0..9e2145a0 100644
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -467,6 +467,7 @@
jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig");
DASSERT(win32GCCls != NULL);
DASSERT(env->IsInstanceOf(compGC, win32GCCls));
+ CHECK_NULL(win32GCCls);
env->SetObjectField(peer, AwtComponent::peerGCID, compGC);
}
}
@@ -530,10 +531,15 @@
if (dw == ERROR_OUTOFMEMORY)
{
jstring errorMsg = JNU_NewStringPlatform(env, L"too many window handles");
- createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError",
+ if (errorMsg == NULL || env->ExceptionCheck()) {
+ env->ExceptionClear();
+ createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "()V");
+ } else {
+ createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError",
"(Ljava/lang/String;)V",
errorMsg);
- env->DeleteLocalRef(errorMsg);
+ env->DeleteLocalRef(errorMsg);
+ }
}
else
{
@@ -542,14 +548,18 @@
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&buf, 0, NULL);
jstring s = JNU_NewStringPlatform(env, buf);
- createError = JNU_NewObjectByName(env, "java/lang/InternalError",
- "(Ljava/lang/String;)V", s);
+ if (s == NULL || env->ExceptionCheck()) {
+ env->ExceptionClear();
+ createError = JNU_NewObjectByName(env, "java/lang/InternalError", "()V");
+ } else {
+ createError = JNU_NewObjectByName(env, "java/lang/InternalError",
+ "(Ljava/lang/String;)V", s);
+ env->DeleteLocalRef(s);
+ }
LocalFree(buf);
- env->DeleteLocalRef(s);
}
- env->SetObjectField(peer, AwtObject::createErrorID, createError);
- if (createError != NULL)
- {
+ if (createError != NULL) {
+ env->SetObjectField(peer, AwtObject::createErrorID, createError);
env->DeleteLocalRef(createError);
}
env->DeleteLocalRef(target);
@@ -1719,9 +1729,11 @@
case WM_IME_SETCONTEXT:
// lParam is passed as pointer and it can be modified.
mr = WmImeSetContext(static_cast<BOOL>(wParam), &lParam);
+ CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
break;
case WM_IME_NOTIFY:
mr = WmImeNotify(wParam, lParam);
+ CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
break;
case WM_IME_STARTCOMPOSITION:
mr = WmImeStartComposition();
@@ -3309,10 +3321,7 @@
if( extKeyCodesCls == NULL) {
jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes");
DASSERT(extKeyCodesClsLocal);
- if (extKeyCodesClsLocal == NULL) {
- /* exception already thrown */
- return;
- }
+ CHECK_NULL(extKeyCodesClsLocal);
extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal);
env->DeleteLocalRef(extKeyCodesClsLocal);
}
@@ -3321,6 +3330,7 @@
getExtendedKeyCodeForChar =
env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I");
DASSERT(getExtendedKeyCodeForChar);
+ CHECK_NULL(getExtendedKeyCodeForChar);
}
jint extJKC; //extended Java key code
@@ -3940,11 +3950,19 @@
if (cClause && rgClauseBoundary && rgClauseReading) {
// convert clause boundary offset array to java array
clauseBoundary = env->NewIntArray(cClause+1);
+ DASSERT(clauseBoundary);
+ CHECK_NULL(clauseBoundary);
env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary);
DASSERT(!safe_ExceptionOccurred(env));
// convert clause reading string array to java array
- clauseReading = env->NewObjectArray(cClause, JNU_ClassString(env), NULL);
+ jclass stringCls = JNU_ClassString(env);
+ DASSERT(stringCls);
+ CHECK_NULL(stringCls);
+ clauseReading = env->NewObjectArray(cClause, stringCls, NULL);
+ env->DeleteLocalRef(stringCls);
+ DASSERT(clauseReading);
+ CHECK_NULL(clauseReading);
for (int i=0; i<cClause; i++) env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]);
DASSERT(!safe_ExceptionOccurred(env));
}
@@ -3963,11 +3981,15 @@
if (cAttrBlock && rgAttrBoundary && rgAttrValue) {
// convert attribute boundary offset array to java array
attrBoundary = env->NewIntArray(cAttrBlock+1);
+ DASSERT(attrBoundary);
+ CHECK_NULL(attrBoundary);
env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary);
DASSERT(!safe_ExceptionOccurred(env));
// convert attribute value byte array to java array
attrValue = env->NewByteArray(cAttrBlock);
+ DASSERT(attrValue);
+ CHECK_NULL(attrValue);
env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue);
DASSERT(!safe_ExceptionOccurred(env));
}
@@ -3978,10 +4000,7 @@
if (wInputMethodCls == NULL) {
jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
DASSERT(wInputMethodClsLocal);
- if (wInputMethodClsLocal == NULL) {
- /* exception already thrown */
- return;
- }
+ CHECK_NULL(wInputMethodClsLocal);
wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
env->DeleteLocalRef(wInputMethodClsLocal);
}
@@ -3992,6 +4011,7 @@
sendIMEventMid = env->GetMethodID(wInputMethodCls, "sendInputMethodEvent",
"(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V");
DASSERT(sendIMEventMid);
+ CHECK_NULL(sendIMEventMid);
}
// call m_InputMethod.sendInputMethod()
@@ -4017,10 +4037,7 @@
if (wInputMethodCls == NULL) {
jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
DASSERT(wInputMethodClsLocal);
- if (wInputMethodClsLocal == NULL) {
- /* exception already thrown */
- return;
- }
+ CHECK_NULL(wInputMethodClsLocal);
wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
env->DeleteLocalRef(wInputMethodClsLocal);
}
@@ -4028,10 +4045,10 @@
// get method ID of sendInputMethodEvent() (run only once)
static jmethodID inqCandPosMid = 0;
if (inqCandPosMid == 0) {
- inqCandPosMid = env->GetMethodID(wInputMethodCls, "inquireCandidatePosition",
- "()V");
+ inqCandPosMid = env->GetMethodID(wInputMethodCls, "inquireCandidatePosition", "()V");
DASSERT(!safe_ExceptionOccurred(env));
DASSERT(inqCandPosMid);
+ CHECK_NULL(inqCandPosMid);
}
// call m_InputMethod.sendInputMethod()
@@ -4070,7 +4087,7 @@
{
if (mr != mrConsume) {
HWND proxy = GetProxyFocusOwner();
- if (proxy != NULL) {
+ if (proxy != NULL && ::IsWindowEnabled(proxy)) {
retVal = ComCtl32Util::GetInstance().DefWindowProc(NULL, proxy, message, wParam, lParam);
mr = mrConsume;
}
@@ -4313,6 +4330,11 @@
if ((int) (drawInfo.itemID) >= 0) {
jobject font = GET_FONT(target, peer);
jstring text = GetItemString(env, target, drawInfo.itemID);
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(font);
+ env->DeleteLocalRef(target);
+ return;
+ }
SIZE size = AwtFont::getMFStringSize(hDC, font, text);
AwtFont::drawMFString(hDC, font, text,
(GetRTL()) ? rect.right - size.cx - 1
@@ -4772,6 +4794,7 @@
keyEventConst = env->GetMethodID(keyEventCls, "<init>",
"(Ljava/awt/Component;IJIICI)V");
DASSERT(keyEventConst);
+ CHECK_NULL(keyEventConst);
}
if (env->EnsureLocalCapacity(2) < 0) {
return;
@@ -4783,6 +4806,10 @@
if (safe_ExceptionOccurred(env)) env->ExceptionDescribe();
DASSERT(!safe_ExceptionOccurred(env));
DASSERT(keyEvent != NULL);
+ if (keyEvent == NULL) {
+ env->DeleteLocalRef(target);
+ return;
+ }
env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode);
if( nativeCode && nativeCode < 256 ) {
env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode));
@@ -4866,10 +4893,7 @@
if (mouseEventCls == NULL) {
jclass mouseEventClsLocal =
env->FindClass("java/awt/event/MouseEvent");
- if (!mouseEventClsLocal) {
- /* exception already thrown */
- return;
- }
+ CHECK_NULL(mouseEventClsLocal);
mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
env->DeleteLocalRef(mouseEventClsLocal);
}
@@ -4882,6 +4906,7 @@
env->GetMethodID(mouseEventCls, "<init>",
"(Ljava/awt/Component;IJIIIIIIZI)V");
DASSERT(mouseEventConst);
+ CHECK_NULL(mouseEventConst);
}
if (env->EnsureLocalCapacity(2) < 0) {
return;
@@ -4894,7 +4919,7 @@
target,
id, when, modifiers,
x+insets.left, y+insets.top,
- xAbs, yAbs,
+ xAbs, yAbs,
clickCount, popupTrigger, button);
if (safe_ExceptionOccurred(env)) {
@@ -4903,6 +4928,7 @@
}
DASSERT(mouseEvent != NULL);
+ CHECK_NULL(mouseEvent);
if (pMsg != 0) {
AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
}
@@ -4931,10 +4957,7 @@
if (mouseWheelEventCls == NULL) {
jclass mouseWheelEventClsLocal =
env->FindClass("java/awt/event/MouseWheelEvent");
- if (!mouseWheelEventClsLocal) {
- /* exception already thrown */
- return;
- }
+ CHECK_NULL(mouseWheelEventClsLocal);
mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal);
env->DeleteLocalRef(mouseWheelEventClsLocal);
}
@@ -4947,6 +4970,7 @@
env->GetMethodID(mouseWheelEventCls, "<init>",
"(Ljava/awt/Component;IJIIIIIIZIIID)V");
DASSERT(mouseWheelEventConst);
+ CHECK_NULL(mouseWheelEventConst);
}
if (env->EnsureLocalCapacity(2) < 0) {
return;
@@ -4963,11 +4987,14 @@
clickCount, popupTrigger,
scrollType, scrollAmount,
roundedWheelRotation, preciseWheelRotation);
- if (safe_ExceptionOccurred(env)) {
+
+ DASSERT(mouseWheelEvent != NULL);
+ if (mouseWheelEvent == NULL || safe_ExceptionOccurred(env)) {
env->ExceptionDescribe();
env->ExceptionClear();
+ env->DeleteLocalRef(target);
+ return;
}
- DASSERT(mouseWheelEvent != NULL);
if (pMsg != NULL) {
AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent);
}
@@ -4992,10 +5019,7 @@
jclass focusEventClsLocal
= env->FindClass("java/awt/event/FocusEvent");
DASSERT(focusEventClsLocal);
- if (focusEventClsLocal == NULL) {
- /* exception already thrown */
- return;
- }
+ CHECK_NULL(focusEventClsLocal);
focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal);
env->DeleteLocalRef(focusEventClsLocal);
}
@@ -5006,6 +5030,7 @@
env->GetMethodID(focusEventCls, "<init>",
"(Ljava/awt/Component;IZLjava/awt/Component;)V");
DASSERT(focusEventConst);
+ CHECK_NULL(focusEventConst);
}
static jclass sequencedEventCls;
@@ -5013,10 +5038,7 @@
jclass sequencedEventClsLocal =
env->FindClass("java/awt/SequencedEvent");
DASSERT(sequencedEventClsLocal);
- if (sequencedEventClsLocal == NULL) {
- /* exception already thrown */
- return;
- }
+ CHECK_NULL(sequencedEventClsLocal);
sequencedEventCls =
(jclass)env->NewGlobalRef(sequencedEventClsLocal);
env->DeleteLocalRef(sequencedEventClsLocal);
@@ -5027,6 +5049,8 @@
sequencedEventConst =
env->GetMethodID(sequencedEventCls, "<init>",
"(Ljava/awt/AWTEvent;)V");
+ DASSERT(sequencedEventConst);
+ CHECK_NULL(sequencedEventConst);
}
if (env->EnsureLocalCapacity(3) < 0) {
@@ -5049,6 +5073,7 @@
env->DeleteLocalRef(jOpposite); jOpposite = NULL;
}
env->DeleteLocalRef(target); target = NULL;
+ CHECK_NULL(focusEvent);
jobject sequencedEvent = env->NewObject(sequencedEventCls,
sequencedEventConst,
@@ -5056,7 +5081,7 @@
DASSERT(!safe_ExceptionOccurred(env));
DASSERT(sequencedEvent != NULL);
env->DeleteLocalRef(focusEvent); focusEvent = NULL;
-
+ CHECK_NULL(sequencedEvent);
SendEvent(sequencedEvent);
env->DeleteLocalRef(sequencedEvent);
@@ -5227,7 +5252,7 @@
"getWheelRotation",
"()I").i;
DASSERT(!safe_ExceptionOccurred(env));
- //DASSERT(wheelAmt);
+ JNU_CHECK_EXCEPTION(env);
DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt);
// convert Java wheel amount value to Win32
@@ -6306,10 +6331,12 @@
{
TRY;
jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent");
+ CHECK_NULL(inputEventClazz);
jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I");
+ CHECK_NULL(getButtonDownMasksID);
jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID);
jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE);
-
+ CHECK_NULL(tmp);
jsize len = env->GetArrayLength(obj);
AwtComponent::masks = SAFE_SIZE_NEW_ARRAY(jint, len);
for (int i = 0; i < len; i++) {
@@ -6322,68 +6349,112 @@
jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer");
DASSERT(peerCls);
+ CHECK_NULL(peerCls);
/* field ids */
AwtComponent::peerID =
env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;");
+ DASSERT(AwtComponent::peerID);
+ CHECK_NULL(AwtComponent::peerID);
+
AwtComponent::xID = env->GetFieldID(cls, "x", "I");
+ DASSERT(AwtComponent::xID);
+ CHECK_NULL(AwtComponent::xID);
+
AwtComponent::yID = env->GetFieldID(cls, "y", "I");
+ DASSERT(AwtComponent::yID);
+ CHECK_NULL(AwtComponent::yID);
+
AwtComponent::heightID = env->GetFieldID(cls, "height", "I");
+ DASSERT(AwtComponent::heightID);
+ CHECK_NULL(AwtComponent::heightID);
+
AwtComponent::widthID = env->GetFieldID(cls, "width", "I");
+ DASSERT(AwtComponent::widthID);
+ CHECK_NULL(AwtComponent::widthID);
+
AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z");
+ DASSERT(AwtComponent::visibleID);
+ CHECK_NULL(AwtComponent::visibleID);
+
AwtComponent::backgroundID =
env->GetFieldID(cls, "background", "Ljava/awt/Color;");
+ DASSERT(AwtComponent::backgroundID);
+ CHECK_NULL(AwtComponent::backgroundID);
+
AwtComponent::foregroundID =
env->GetFieldID(cls, "foreground", "Ljava/awt/Color;");
+ DASSERT(AwtComponent::foregroundID);
+ CHECK_NULL(AwtComponent::foregroundID);
+
AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z");
+ DASSERT(AwtComponent::enabledID);
+ CHECK_NULL(AwtComponent::enabledID);
+
AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;");
+ DASSERT(AwtComponent::parentID);
+ CHECK_NULL(AwtComponent::parentID);
+
AwtComponent::graphicsConfigID =
env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;");
+ DASSERT(AwtComponent::graphicsConfigID);
+ CHECK_NULL(AwtComponent::graphicsConfigID);
+
AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z");
+ DASSERT(AwtComponent::focusableID);
+ CHECK_NULL(AwtComponent::focusableID);
AwtComponent::appContextID = env->GetFieldID(cls, "appContext",
"Lsun/awt/AppContext;");
+ DASSERT(AwtComponent::appContextID);
+ CHECK_NULL(AwtComponent::appContextID);
AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig",
"Lsun/awt/Win32GraphicsConfig;");
+ DASSERT(AwtComponent::peerGCID);
+ CHECK_NULL(AwtComponent::peerGCID);
AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J");
+ DASSERT(AwtComponent::hwndID);
+ CHECK_NULL(AwtComponent::hwndID);
AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;");
+ DASSERT(AwtComponent::cursorID);
+ CHECK_NULL(AwtComponent::cursorID);
/* method ids */
AwtComponent::getFontMID =
env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;");
+ DASSERT(AwtComponent::getFontMID);
+ CHECK_NULL(AwtComponent::getFontMID);
+
AwtComponent::getToolkitMID =
env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;");
+ DASSERT(AwtComponent::getToolkitMID);
+ CHECK_NULL(AwtComponent::getToolkitMID);
+
AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z");
+ DASSERT(AwtComponent::isEnabledMID);
+ CHECK_NULL(AwtComponent::isEnabledMID);
+
AwtComponent::getLocationOnScreenMID =
env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;");
+ DASSERT(AwtComponent::getLocationOnScreenMID);
+ CHECK_NULL(AwtComponent::getLocationOnScreenMID);
+
AwtComponent::replaceSurfaceDataMID =
env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
+ DASSERT(AwtComponent::replaceSurfaceDataMID);
+ CHECK_NULL(AwtComponent::replaceSurfaceDataMID);
+
AwtComponent::replaceSurfaceDataLaterMID =
env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
- AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
-
- DASSERT(AwtComponent::xID);
- DASSERT(AwtComponent::yID);
- DASSERT(AwtComponent::heightID);
- DASSERT(AwtComponent::widthID);
- DASSERT(AwtComponent::visibleID);
- DASSERT(AwtComponent::backgroundID);
- DASSERT(AwtComponent::foregroundID);
- DASSERT(AwtComponent::enabledID);
- DASSERT(AwtComponent::parentID);
- DASSERT(AwtComponent::hwndID);
-
- DASSERT(AwtComponent::getFontMID);
- DASSERT(AwtComponent::getToolkitMID);
- DASSERT(AwtComponent::isEnabledMID);
- DASSERT(AwtComponent::getLocationOnScreenMID);
- DASSERT(AwtComponent::replaceSurfaceDataMID);
DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
- DASSERT(AwtComponent::disposeLaterMID);
+ CHECK_NULL(AwtComponent::replaceSurfaceDataLaterMID);
+ AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
+ DASSERT(AwtComponent::disposeLaterMID);
+ CHECK_NULL(AwtComponent::disposeLaterMID);
CATCH_BAD_ALLOC;
}
diff --git a/jdk/src/windows/native/sun/windows/awt_DataTransferer.cpp b/jdk/src/windows/native/sun/windows/awt_DataTransferer.cpp
index 77a87b2..9ebc2c6 100644
--- a/jdk/src/windows/native/sun/windows/awt_DataTransferer.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_DataTransferer.cpp
@@ -274,6 +274,9 @@
jclass str_clazz = env->FindClass("java/lang/String");
DASSERT(str_clazz != NULL);
+ if (str_clazz == NULL) {
+ throw std::bad_alloc();
+ }
jobjectArray filenames = env->NewObjectArray(nFilenames, str_clazz,
NULL);
if (filenames == NULL) {
@@ -827,6 +830,7 @@
TRY;
LPCTSTR cStr = JNU_GetStringPlatformChars(env, str, NULL);
+ CHECK_NULL_RETURN(cStr, 0);
jlong value = ::RegisterClipboardFormat(cStr);
JNU_ReleaseStringPlatformChars(env, str, cStr);
diff --git a/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp b/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp
index 7d68f25..21a4b00 100644
--- a/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -83,13 +83,19 @@
HDC dc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
if (dc != NULL) {
- SetFontProperty(dc, ANSI_FIXED_FONT, TEXT("win.ansiFixed.font"));
- SetFontProperty(dc, ANSI_VAR_FONT, TEXT("win.ansiVar.font"));
- SetFontProperty(dc, DEVICE_DEFAULT_FONT, TEXT("win.deviceDefault.font"));
- SetFontProperty(dc, DEFAULT_GUI_FONT, TEXT("win.defaultGUI.font"));
- SetFontProperty(dc, OEM_FIXED_FONT, TEXT("win.oemFixed.font"));
- SetFontProperty(dc, SYSTEM_FONT, TEXT("win.system.font"));
- SetFontProperty(dc, SYSTEM_FIXED_FONT, TEXT("win.systemFixed.font"));
+ try {
+ SetFontProperty(dc, ANSI_FIXED_FONT, TEXT("win.ansiFixed.font"));
+ SetFontProperty(dc, ANSI_VAR_FONT, TEXT("win.ansiVar.font"));
+ SetFontProperty(dc, DEVICE_DEFAULT_FONT, TEXT("win.deviceDefault.font"));
+ SetFontProperty(dc, DEFAULT_GUI_FONT, TEXT("win.defaultGUI.font"));
+ SetFontProperty(dc, OEM_FIXED_FONT, TEXT("win.oemFixed.font"));
+ SetFontProperty(dc, SYSTEM_FONT, TEXT("win.system.font"));
+ SetFontProperty(dc, SYSTEM_FIXED_FONT, TEXT("win.systemFixed.font"));
+ }
+ catch (std::bad_alloc&) {
+ DeleteDC(dc);
+ throw;
+ }
DeleteDC(dc);
}
}
@@ -206,24 +212,35 @@
LPTSTR value;
value = getXPStylePropFromReg(TEXT("ThemeActive"));
- SetBooleanProperty(TEXT("win.xpstyle.themeActive"), (value != NULL && *value == _T('1')));
- if (value != NULL) {
- free(value);
+ try {
+ SetBooleanProperty(TEXT("win.xpstyle.themeActive"), (value != NULL && *value == _T('1')));
+ if (value != NULL) {
+ free(value);
+ value = NULL;
+ }
+ value = getXPStylePropFromReg(TEXT("DllName"));
+ if (value != NULL) {
+ SetStringProperty(TEXT("win.xpstyle.dllName"), value);
+ free(value);
+ value = NULL;
+ }
+ value = getXPStylePropFromReg(TEXT("SizeName"));
+ if (value != NULL) {
+ SetStringProperty(TEXT("win.xpstyle.sizeName"), value);
+ free(value);
+ value = NULL;
+ }
+ value = getXPStylePropFromReg(TEXT("ColorName"));
+ if (value != NULL) {
+ SetStringProperty(TEXT("win.xpstyle.colorName"), value);
+ free(value);
+ }
}
- value = getXPStylePropFromReg(TEXT("DllName"));
- if (value != NULL) {
- SetStringProperty(TEXT("win.xpstyle.dllName"), value);
- free(value);
- }
- value = getXPStylePropFromReg(TEXT("SizeName"));
- if (value != NULL) {
- SetStringProperty(TEXT("win.xpstyle.sizeName"), value);
- free(value);
- }
- value = getXPStylePropFromReg(TEXT("ColorName"));
- if (value != NULL) {
- SetStringProperty(TEXT("win.xpstyle.colorName"), value);
- free(value);
+ catch (std::bad_alloc&) {
+ if (value != NULL) {
+ free(value);
+ }
+ throw;
}
}
@@ -564,27 +581,37 @@
// Shell Icon BPP - only honored on platforms before XP
value = getWindowsPropFromReg(TEXT("Control Panel\\Desktop\\WindowMetrics"),
TEXT("Shell Icon BPP"), &valueType);
- if (value != NULL) {
- if (valueType == REG_SZ) {
- SetStringProperty(TEXT("win.icon.shellIconBPP"), value);
+
+ try {
+ if (value != NULL) {
+ if (valueType == REG_SZ) {
+ SetStringProperty(TEXT("win.icon.shellIconBPP"), value);
+ }
+ free(value);
+ value = NULL;
}
- free(value);
+
+
+ // The following registry settings control the file chooser places bar
+ // under the Windows L&F. These settings are not present by default, but
+ // can be enabled using the TweakUI tool from Microsoft. For more info,
+ // see http://msdn.microsoft.com/msdnmag/issues/1100/Registry/
+
+ // NoPlacesBar is a REG_DWORD, with values 0 or 1
+ value = getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32"),
+ TEXT("NoPlacesBar"), &valueType);
+ if (value != NULL) {
+ if (valueType == REG_DWORD) {
+ SetBooleanProperty(TEXT("win.comdlg.noPlacesBar"), (BOOL)((int)*value != 0));
+ }
+ free(value);
+ }
}
-
-
- // The following registry settings control the file chooser places bar
- // under the Windows L&F. These settings are not present by default, but
- // can be enabled using the TweakUI tool from Microsoft. For more info,
- // see http://msdn.microsoft.com/msdnmag/issues/1100/Registry/
-
- // NoPlacesBar is a REG_DWORD, with values 0 or 1
- value = getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32"),
- TEXT("NoPlacesBar"), &valueType);
- if (value != NULL) {
- if (valueType == REG_DWORD) {
- SetBooleanProperty(TEXT("win.comdlg.noPlacesBar"), (BOOL)((int)*value != 0));
+ catch (std::bad_alloc&) {
+ if (value != NULL) {
+ free(value);
}
- free(value);
+ throw;
}
LPTSTR valueName = TEXT("PlaceN");
@@ -592,7 +619,15 @@
lstrcpy(valueNameBuf, valueName);
LPTSTR propKey = TEXT("win.comdlg.placesBarPlaceN");
- LPTSTR propKeyBuf = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (lstrlen(propKey) + 1), sizeof(TCHAR));
+
+ LPTSTR propKeyBuf;
+ try {
+ propKeyBuf = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (lstrlen(propKey) + 1), sizeof(TCHAR));
+ }
+ catch (std::bad_alloc&) {
+ free(valueNameBuf);
+ throw;
+ }
lstrcpy(propKeyBuf, propKey);
int i = 0;
@@ -601,20 +636,31 @@
propKeyBuf[25] = valueNameBuf[5];
LPTSTR key = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32\\PlacesBar");
- if ((value = getWindowsPropFromReg(key, valueNameBuf, &valueType)) != NULL) {
- if (valueType == REG_DWORD) {
- // Value is a CSIDL
- SetIntegerProperty(propKeyBuf, (int)*value);
- } else {
- // Value is a path
- SetStringProperty(propKeyBuf, value);
+ try {
+ value = NULL;
+ if ((value = getWindowsPropFromReg(key, valueNameBuf, &valueType)) != NULL) {
+ if (valueType == REG_DWORD) {
+ // Value is a CSIDL
+ SetIntegerProperty(propKeyBuf, (int)*value);
+ } else {
+ // Value is a path
+ SetStringProperty(propKeyBuf, value);
+ }
+ free(value);
}
- free(value);
+ }
+ catch (std::bad_alloc&) {
+ if (value != NULL) {
+ free(value);
+ }
+ free(propKeyBuf);
+ free(valueNameBuf);
+ throw;
}
} while (value != NULL);
- free(valueNameBuf);
free(propKeyBuf);
+ free(valueNameBuf);
}
void AwtDesktopProperties::GetSoundEvents() {
@@ -656,14 +702,26 @@
void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) {
jstring key = JNU_NewStringPlatform(GetEnv(), propName);
+ if (key == NULL) {
+ throw std::bad_alloc();
+ }
+ jstring jValue = JNU_NewStringPlatform(GetEnv(), value);
+ if (jValue == NULL) {
+ GetEnv()->DeleteLocalRef(key);
+ throw std::bad_alloc();
+ }
GetEnv()->CallVoidMethod(self,
AwtDesktopProperties::setStringPropertyID,
- key, JNU_NewStringPlatform(GetEnv(), value));
+ key, jValue);
+ GetEnv()->DeleteLocalRef(jValue);
GetEnv()->DeleteLocalRef(key);
}
void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) {
jstring key = JNU_NewStringPlatform(GetEnv(), propName);
+ if (key == NULL) {
+ throw std::bad_alloc();
+ }
GetEnv()->CallVoidMethod(self,
AwtDesktopProperties::setIntegerPropertyID,
key, (jint)value);
@@ -672,6 +730,9 @@
void AwtDesktopProperties::SetBooleanProperty(LPCTSTR propName, BOOL value) {
jstring key = JNU_NewStringPlatform(GetEnv(), propName);
+ if (key == NULL) {
+ throw std::bad_alloc();
+ }
GetEnv()->CallVoidMethod(self,
AwtDesktopProperties::setBooleanPropertyID,
key, value ? JNI_TRUE : JNI_FALSE);
@@ -680,6 +741,9 @@
void AwtDesktopProperties::SetColorProperty(LPCTSTR propName, DWORD value) {
jstring key = JNU_NewStringPlatform(GetEnv(), propName);
+ if (key == NULL) {
+ throw std::bad_alloc();
+ }
GetEnv()->CallVoidMethod(self,
AwtDesktopProperties::setColorPropertyID,
key, GetRValue(value), GetGValue(value),
@@ -720,6 +784,11 @@
else {
fontName = JNU_NewStringPlatform(GetEnv(), face);
}
+ if (fontName == NULL) {
+ delete[] face;
+ throw std::bad_alloc();
+ }
+
jint pointSize = metrics.tmHeight -
metrics.tmInternalLeading;
jint style = java_awt_Font_PLAIN;
@@ -732,11 +801,16 @@
}
jstring key = JNU_NewStringPlatform(GetEnv(), propName);
+ if (key == NULL) {
+ GetEnv()->DeleteLocalRef(fontName);
+ delete[] face;
+ throw std::bad_alloc();
+ }
GetEnv()->CallVoidMethod(self,
AwtDesktopProperties::setFontPropertyID,
key, fontName, style, pointSize);
- GetEnv()->DeleteLocalRef(fontName);
GetEnv()->DeleteLocalRef(key);
+ GetEnv()->DeleteLocalRef(fontName);
}
}
delete[] face;
@@ -750,7 +824,9 @@
jint style;
fontName = JNU_NewStringPlatform(GetEnv(), font.lfFaceName);
-
+ if (fontName == NULL) {
+ throw std::bad_alloc();
+ }
#if 0
HDC hdc;
int pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
@@ -773,22 +849,31 @@
}
jstring key = JNU_NewStringPlatform(GetEnv(), propName);
+ if (key == NULL) {
+ GetEnv()->DeleteLocalRef(fontName);
+ throw std::bad_alloc();
+ }
GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID,
key, fontName, style, pointSize);
-
- GetEnv()->DeleteLocalRef(fontName);
GetEnv()->DeleteLocalRef(key);
+ GetEnv()->DeleteLocalRef(fontName);
}
void AwtDesktopProperties::SetSoundProperty(LPCTSTR propName, LPCTSTR winEventName) {
jstring key = JNU_NewStringPlatform(GetEnv(), propName);
+ if (key == NULL) {
+ throw std::bad_alloc();
+ }
jstring event = JNU_NewStringPlatform(GetEnv(), winEventName);
+ if (event == NULL) {
+ GetEnv()->DeleteLocalRef(key);
+ throw std::bad_alloc();
+ }
GetEnv()->CallVoidMethod(self,
AwtDesktopProperties::setSoundPropertyID,
key, event);
-
- GetEnv()->DeleteLocalRef(key);
GetEnv()->DeleteLocalRef(event);
+ GetEnv()->DeleteLocalRef(key);
}
void AwtDesktopProperties::PlayWindowsSound(LPCTSTR event) {
@@ -814,24 +899,37 @@
AwtDesktopProperties::pDataID = env->GetFieldID(cls, "pData", "J");
DASSERT(AwtDesktopProperties::pDataID != 0);
+ CHECK_NULL(AwtDesktopProperties::pDataID);
- AwtDesktopProperties::setBooleanPropertyID = env->GetMethodID(cls, "setBooleanProperty", "(Ljava/lang/String;Z)V");
+ AwtDesktopProperties::setBooleanPropertyID =
+ env->GetMethodID(cls, "setBooleanProperty", "(Ljava/lang/String;Z)V");
DASSERT(AwtDesktopProperties::setBooleanPropertyID != 0);
+ CHECK_NULL(AwtDesktopProperties::setBooleanPropertyID);
- AwtDesktopProperties::setIntegerPropertyID = env->GetMethodID(cls, "setIntegerProperty", "(Ljava/lang/String;I)V");
+ AwtDesktopProperties::setIntegerPropertyID =
+ env->GetMethodID(cls, "setIntegerProperty", "(Ljava/lang/String;I)V");
DASSERT(AwtDesktopProperties::setIntegerPropertyID != 0);
+ CHECK_NULL(AwtDesktopProperties::setIntegerPropertyID);
- AwtDesktopProperties::setStringPropertyID = env->GetMethodID(cls, "setStringProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
+ AwtDesktopProperties::setStringPropertyID =
+ env->GetMethodID(cls, "setStringProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
DASSERT(AwtDesktopProperties::setStringPropertyID != 0);
+ CHECK_NULL(AwtDesktopProperties::setStringPropertyID);
- AwtDesktopProperties::setColorPropertyID = env->GetMethodID(cls, "setColorProperty", "(Ljava/lang/String;III)V");
+ AwtDesktopProperties::setColorPropertyID =
+ env->GetMethodID(cls, "setColorProperty", "(Ljava/lang/String;III)V");
DASSERT(AwtDesktopProperties::setColorPropertyID != 0);
+ CHECK_NULL(AwtDesktopProperties::setColorPropertyID);
- AwtDesktopProperties::setFontPropertyID = env->GetMethodID(cls, "setFontProperty", "(Ljava/lang/String;Ljava/lang/String;II)V");
+ AwtDesktopProperties::setFontPropertyID =
+ env->GetMethodID(cls, "setFontProperty", "(Ljava/lang/String;Ljava/lang/String;II)V");
DASSERT(AwtDesktopProperties::setFontPropertyID != 0);
+ CHECK_NULL(AwtDesktopProperties::setFontPropertyID);
- AwtDesktopProperties::setSoundPropertyID = env->GetMethodID(cls, "setSoundProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
+ AwtDesktopProperties::setSoundPropertyID =
+ env->GetMethodID(cls, "setSoundProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
DASSERT(AwtDesktopProperties::setSoundPropertyID != 0);
+ CHECK_NULL(AwtDesktopProperties::setSoundPropertyID);
CATCH_BAD_ALLOC;
}
diff --git a/jdk/src/windows/native/sun/windows/awt_DnDDS.cpp b/jdk/src/windows/native/sun/windows/awt_DnDDS.cpp
index f9100ba..27999b6 100644
--- a/jdk/src/windows/native/sun/windows/awt_DnDDS.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_DnDDS.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -643,6 +643,7 @@
m_lastmods == modifiers) {//cannot move before cursor change
call_dSCmouseMoved(env, m_peer,
m_actions, modifiers, dragPoint.x, dragPoint.y);
+ JNU_CHECK_EXCEPTION_RETURN(env, E_UNEXPECTED);
m_dragPoint = dragPoint;
}
@@ -977,6 +978,10 @@
if ((matchedFormatEtc.tymed & TYMED_ISTREAM) != 0) {
jboolean isCopy;
jbyte *bBytes = env->GetByteArrayElements(bytes, &isCopy);
+ if (bBytes == NULL) {
+ env->PopLocalFrame(NULL);
+ return E_UNEXPECTED;
+ }
ULONG act;
HRESULT res = pmedium->pstm->Write((const void *)bBytes, (ULONG)nBytes,
diff --git a/jdk/src/windows/native/sun/windows/awt_DnDDT.cpp b/jdk/src/windows/native/sun/windows/awt_DnDDT.cpp
index 7944c05..8739fc8 100644
--- a/jdk/src/windows/native/sun/windows/awt_DnDDT.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_DnDDT.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -603,6 +603,10 @@
jobject local = JNU_NewStringPlatform(
env,
pmedium->lpszFileName);
+ if (env->ExceptionCheck()) {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
jstring fileName = (jstring)env->NewGlobalRef(local);
env->DeleteLocalRef(local);
@@ -1220,8 +1224,6 @@
/*****************************************************************************/
-jclass WDTCPIStreamWrapper::javaIOExceptionClazz = (jclass)NULL;
-
/**
* construct a wrapper
*/
@@ -1233,16 +1235,6 @@
m_istream = stgmedium->pstm;
m_istream->AddRef();
m_mutex = ::CreateMutex(NULL, FALSE, NULL);
-
- if (javaIOExceptionClazz == (jclass)NULL) {
- javaIOExceptionClazz = env->FindClass("java/io/IOException");
-
- if (JNU_IsNull(env, javaIOExceptionClazz)) {
- env->ThrowNew(env->FindClass("java/lang/ClassNotFoundException"),
- "Cant find java/io/IOException"
- );
- }
- }
}
/**
@@ -1291,12 +1283,12 @@
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (m_istream->Stat(&m_statstg, STATFLAG_NONAME) != S_OK) {
- env->ThrowNew(javaIOExceptionClazz, "IStream::Stat() failed");
+ JNU_ThrowIOException(env, "IStream::Stat() failed");
return 0;
}
if (m_statstg.cbSize.QuadPart > 0x7ffffffL) {
- env->ThrowNew(javaIOExceptionClazz, "IStream::Stat() cbSize > 0x7ffffff");
+ JNU_ThrowIOException(env, "IStream::Stat() cbSize > 0x7ffffff");
return 0;
}
@@ -1349,7 +1341,7 @@
return (jint)(actual == 0 ? -1 : b);
default:
- env->ThrowNew(javaIOExceptionClazz, "IStream::Read failed");
+ JNU_ThrowIOException(env, "IStream::Read failed");
}
return (jint)-1;
}
@@ -1394,6 +1386,7 @@
ULONG actual = 0;
jbyte* local = env->GetByteArrayElements(buf, &isCopy);
HRESULT res;
+ CHECK_NULL_RETURN(local, (jint)-1);
switch (res = m_istream->Read((void *)(local + off), (ULONG)len, &actual)) {
case S_FALSE:
@@ -1406,7 +1399,7 @@
default:
env->ReleaseByteArrayElements(buf, local, JNI_ABORT);
- env->ThrowNew(javaIOExceptionClazz, "IStream::Read failed");
+ JNU_ThrowIOException(env, "IStream::Read failed");
}
return (jint)-1;
diff --git a/jdk/src/windows/native/sun/windows/awt_Event.cpp b/jdk/src/windows/native/sun/windows/awt_Event.cpp
index 445ae87..e267285 100644
--- a/jdk/src/windows/native/sun/windows/awt_Event.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Event.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2014, 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
@@ -45,12 +45,16 @@
TRY;
AwtEvent::targetID = env->GetFieldID(cls, "target", "Ljava/lang/Object;");
- AwtEvent::xID = env->GetFieldID(cls, "x", "I");
- AwtEvent::yID = env->GetFieldID(cls, "y", "I");
-
DASSERT(AwtEvent::targetID != NULL);
+ CHECK_NULL(AwtEvent::targetID);
+
+ AwtEvent::xID = env->GetFieldID(cls, "x", "I");
DASSERT(AwtEvent::xID != NULL);
+ CHECK_NULL(AwtEvent::xID);
+
+ AwtEvent::yID = env->GetFieldID(cls, "y", "I");
DASSERT(AwtEvent::yID != NULL);
+ CHECK_NULL(AwtEvent::yID);
CATCH_BAD_ALLOC;
}
diff --git a/jdk/src/windows/native/sun/windows/awt_Frame.cpp b/jdk/src/windows/native/sun/windows/awt_Frame.cpp
index 1195491..a4d50fa 100644
--- a/jdk/src/windows/native/sun/windows/awt_Frame.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Frame.cpp
@@ -342,6 +342,8 @@
case WM_IME_STARTCOMPOSITION:
case WM_IME_ENDCOMPOSITION:
case WM_IME_COMPOSITION:
+ case WM_IME_SETCONTEXT:
+ case WM_IME_NOTIFY:
case WM_IME_CONTROL:
case WM_IME_COMPOSITIONFULL:
case WM_IME_SELECT:
diff --git a/jdk/src/windows/native/sun/windows/awt_InputTextInfor.cpp b/jdk/src/windows/native/sun/windows/awt_InputTextInfor.cpp
index bbe8a84..4ccf0d5 100644
--- a/jdk/src/windows/native/sun/windows/awt_InputTextInfor.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_InputTextInfor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -132,6 +132,7 @@
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (m_cStrW > 0) {
m_jtext = MakeJavaString(env, m_lpStrW, m_cStrW);
+ JNU_CHECK_EXCEPTION_RETURN(env, -1);
}
// Merge the string if necessary
@@ -251,6 +252,13 @@
} else {
readingClauseW[cls] = MakeJavaString(env, lpHWStrW, cHWStrW);
}
+ if (env->ExceptionCheck()) {
+ lpBndClauseW = NULL;
+ lpReadingClauseW = NULL;
+ delete [] bndClauseW;
+ delete [] readingClauseW;
+ return 0;
+ }
}
else {
readingClauseW[cls] = NULL;
diff --git a/jdk/src/windows/native/sun/windows/awt_Insets.cpp b/jdk/src/windows/native/sun/windows/awt_Insets.cpp
index 3241bc8..ee90495 100644
--- a/jdk/src/windows/native/sun/windows/awt_Insets.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Insets.cpp
@@ -46,14 +46,20 @@
TRY;
AwtInsets::leftID = env->GetFieldID(cls, "left", "I");
- AwtInsets::rightID = env->GetFieldID(cls, "right", "I");
- AwtInsets::topID = env->GetFieldID(cls, "top", "I");
- AwtInsets::bottomID = env->GetFieldID(cls, "bottom", "I");
-
DASSERT(AwtInsets::leftID != NULL);
+ CHECK_NULL(AwtInsets::leftID);
+
+ AwtInsets::rightID = env->GetFieldID(cls, "right", "I");
DASSERT(AwtInsets::rightID != NULL);
+ CHECK_NULL(AwtInsets::rightID);
+
+ AwtInsets::topID = env->GetFieldID(cls, "top", "I");
DASSERT(AwtInsets::topID != NULL);
+ CHECK_NULL(AwtInsets::topID);
+
+ AwtInsets::bottomID = env->GetFieldID(cls, "bottom", "I");
DASSERT(AwtInsets::bottomID != NULL);
+ CHECK_NULL(AwtInsets::bottomID);
CATCH_BAD_ALLOC;
}
diff --git a/jdk/src/windows/native/sun/windows/awt_MouseEvent.cpp b/jdk/src/windows/native/sun/windows/awt_MouseEvent.cpp
index d373b52..682c6e2 100644
--- a/jdk/src/windows/native/sun/windows/awt_MouseEvent.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_MouseEvent.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2014, 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
@@ -45,12 +45,16 @@
TRY;
AwtMouseEvent::xID = env->GetFieldID(cls, "x", "I");
- AwtMouseEvent::yID = env->GetFieldID(cls, "y", "I");
- AwtMouseEvent::buttonID = env->GetFieldID(cls, "button", "I");
-
DASSERT(AwtMouseEvent::xID != NULL);
+ CHECK_NULL(AwtMouseEvent::xID);
+
+ AwtMouseEvent::yID = env->GetFieldID(cls, "y", "I");
DASSERT(AwtMouseEvent::yID != NULL);
+ CHECK_NULL(AwtMouseEvent::yID);
+
+ AwtMouseEvent::buttonID = env->GetFieldID(cls, "button", "I");
DASSERT(AwtMouseEvent::buttonID != NULL);
+ CHECK_NULL(AwtMouseEvent::buttonID);
CATCH_BAD_ALLOC;
}
diff --git a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp
index 6db838f..b9d818e 100644
--- a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -281,21 +281,15 @@
static long convertFromPoints(double value, int units);
static double convertToPoints(long value, int units);
void setCapabilities(JNIEnv *env, jobject self, HDC printDC);
-static inline WORD getPrintPaperSize(JNIEnv *env, jobject self);
-static inline void setPrintPaperSize(JNIEnv *env, jobject self, WORD sz);
-static jint getIntField(JNIEnv *env, jobject self, const char *fieldName);
-static jlong getLongField(JNIEnv *env, jobject self, const char *fieldName);
-static void setIntField(JNIEnv *env, jobject self,
- const char *fieldName, jint value);
-static void setLongField(JNIEnv *env, jobject self,
- const char *fieldName, jlong value);
-static jfieldID getIdOfIntField(JNIEnv *env, jobject self,
+static inline WORD getPrintPaperSize(JNIEnv *env, jboolean* err, jobject self);
+static inline jboolean setPrintPaperSize(JNIEnv *env, jobject self, WORD sz);
+static jint getIntField(JNIEnv *env, jboolean* err, jobject self, const char *fieldName);
+static jboolean setIntField(JNIEnv *env, jobject self,
+ const char *fieldName, jint value);
+static jboolean getBooleanField(JNIEnv *env, jboolean* err, jobject self,
const char *fieldName);
-static jfieldID getIdOfLongField(JNIEnv *env, jobject self,
- const char *fieldName);
-static void setBooleanField(JNIEnv *env, jobject self,
+static jboolean setBooleanField(JNIEnv *env, jobject self,
const char *fieldName, jboolean value);
-
static jbyte *findNonWhite(jbyte *image, long sy, long width, long height,
long scanLineStride, long *numLinesP);
static jbyte *findWhite(jbyte *image, long sy, long width, long height,
@@ -577,7 +571,8 @@
* If both are null, then there is no default printer.
*/
if ((setup.hDevMode == NULL) && (setup.hDevNames == NULL)) {
- return JNI_FALSE;
+ doIt = JNI_FALSE;
+ goto done;
}
} else {
int measure = PSD_INTHOUSANDTHSOFINCHES;
@@ -602,8 +597,11 @@
* into the Windows setup structure so that the format can
* be displayed in the dialog.
*/
- pageFormatToSetup(env, self, page, &setup,
- AwtPrintControl::getPrintDC(env, self));
+ pageFormatToSetup(env, self, page, &setup, AwtPrintControl::getPrintDC(env, self));
+ if (env->ExceptionCheck()) {
+ doIt = JNI_FALSE;
+ goto done;
+ }
setup.lpfnPageSetupHook = reinterpret_cast<LPPAGESETUPHOOK>(pageDlgHook);
setup.Flags = PSD_ENABLEPAGESETUPHOOK | PSD_MARGINS;
@@ -614,7 +612,10 @@
if (ret) {
jobject paper = getPaper(env, page);
-
+ if (paper == NULL) {
+ doIt = JNI_FALSE;
+ goto done;
+ }
int units = setup.Flags & PSD_INTHOUSANDTHSOFINCHES ?
MM_HIENGLISH :
MM_HIMETRIC;
@@ -653,19 +654,33 @@
* and place them into a Paper instance.
*/
setPaperValues(env, paper, &paperSize, &margins, units);
-
- /* Put the updated Paper instance and the orientation into
+ if (env->ExceptionCheck()) {
+ doIt = JNI_FALSE;
+ goto done;
+ }
+ /*
+ * Put the updated Paper instance and the orientation into
* the PageFormat.
*/
setPaper(env, page, paper);
-
+ if (env->ExceptionCheck()) {
+ doIt = JNI_FALSE;
+ goto done;
+ }
setPageFormatOrientation(env, page, orientation);
-
+ if (env->ExceptionCheck()) {
+ doIt = JNI_FALSE;
+ goto done;
+ }
if (setup.hDevMode != NULL) {
DEVMODE *devmode = (DEVMODE *)::GlobalLock(setup.hDevMode);
if (devmode != NULL) {
if (devmode->dmFields & DM_PAPERSIZE) {
- setPrintPaperSize(env, self, devmode->dmPaperSize);
+ jboolean err = setPrintPaperSize(env, self, devmode->dmPaperSize);
+ if (err) {
+ doIt = JNI_FALSE;
+ goto done;
+ }
}
}
::GlobalUnlock(setup.hDevMode);
@@ -673,8 +688,6 @@
doIt = JNI_TRUE;
}
- DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L);
-
AwtDialog::CheckUninstallModalHook();
AwtDialog::ModalActivateNextWindow(NULL, target, peer);
@@ -689,6 +702,7 @@
AwtPrintControl::setPrintHDName(env, self, setup.hDevNames);
}
+done:
env->DeleteGlobalRef(peerGlobalRef);
if (target != NULL) {
env->DeleteLocalRef(target);
@@ -826,8 +840,14 @@
margins.bottom = convertFromPoints(72, units);;
jobject paper = getPaper(env, page);
+ if (paper == NULL) {
+ goto done;
+ }
+
setPaperValues(env, paper, &paperSize, &margins, units);
+ if (env->ExceptionCheck()) goto done;
setPaper(env, page, paper);
+ if (env->ExceptionCheck()) goto done;
if ((pDevMode->dmFields & DM_ORIENTATION) &&
(pDevMode->dmOrientation == DMORIENT_LANDSCAPE)) {
@@ -837,8 +857,10 @@
}
} else {
- setBooleanField(env, self, NO_DEFAULTPRINTER_STR, (jint)JNI_TRUE);
+ setBooleanField(env, self, NO_DEFAULTPRINTER_STR, (jint)JNI_TRUE);
}
+
+done:
::GlobalFree(pDevMode);
free ((LPTSTR) printerName);
@@ -890,9 +912,7 @@
}
}
- if (printDC == NULL) {
- return;
- }
+ JNI_CHECK_NULL_GOTO(printDC, "Invalid printDC", done);
/* We try to mitigate the effects of floating point rounding errors
* by only setting a value if it would differ from the value in the
@@ -903,7 +923,9 @@
const double epsilon = 0.10;
jdouble paperWidth, paperHeight;
- WORD dmPaperSize = getPrintPaperSize(env, self);
+ jboolean err;
+ WORD dmPaperSize = getPrintPaperSize(env, &err, self);
+ if (err) goto done;
double ix, iy, iw, ih, pw, ph;
@@ -911,17 +933,24 @@
jmethodID getID;
jclass paperClass = env->GetObjectClass(origPaper);
+ JNI_CHECK_NULL_GOTO(paperClass, "paper class not found", done);
getID = env->GetMethodID(paperClass, GETWIDTH_STR, GETWIDTH_SIG);
+ JNI_CHECK_NULL_GOTO(getID, "no getWidth method", done);
pw = env->CallDoubleMethod(origPaper, getID);
getID = env->GetMethodID(paperClass, GETHEIGHT_STR, GETHEIGHT_SIG);
+ JNI_CHECK_NULL_GOTO(getID, "no getHeight method", done);
ph = env->CallDoubleMethod(origPaper, getID);
getID = env->GetMethodID(paperClass, GETIMG_X_STR, GETIMG_X_SIG);
+ JNI_CHECK_NULL_GOTO(getID, "no getX method", done);
ix = env->CallDoubleMethod(origPaper, getID);
getID = env->GetMethodID(paperClass, GETIMG_Y_STR, GETIMG_Y_SIG);
+ JNI_CHECK_NULL_GOTO(getID, "no getY method", done);
iy = env->CallDoubleMethod(origPaper, getID);
getID = env->GetMethodID(paperClass, GETIMG_W_STR, GETIMG_W_SIG);
+ JNI_CHECK_NULL_GOTO(getID, "no getW method", done);
iw = env->CallDoubleMethod(origPaper, getID);
getID = env->GetMethodID(paperClass, GETIMG_H_STR, GETIMG_H_SIG);
+ JNI_CHECK_NULL_GOTO(getID, "no getH method", done);
ih = env->CallDoubleMethod(origPaper, getID);
matchPaperSize(printDC, hDevMode, hDevNames, pw, ph,
@@ -1014,12 +1043,16 @@
jmethodID setSizeID = env->GetMethodID(paperClass,
SETSIZE_STR, SETSIZE_SIG);
+ JNI_CHECK_NULL_GOTO(setSizeID, "no setSize method", done);
+
jmethodID setImageableID = env->GetMethodID(paperClass,
SETIMAGEABLE_STR, SETIMAGEABLE_SIG);
+ JNI_CHECK_NULL_GOTO(setImageableID, "no setImageable method", done);
env->CallVoidMethod(newPaper, setSizeID, paperWidth, paperHeight);
env->CallVoidMethod(newPaper, setImageableID, ix, iy, iw, ih);
+done:
/* Free any resources allocated */
if (privateDC == TRUE) {
if (printDC != NULL) {
@@ -1066,6 +1099,7 @@
JNIEXPORT void JNICALL
Java_sun_awt_windows_WPrinterJob_initPrinter(JNIEnv *env, jobject self) {
TRY;
+ jboolean err;
initPrinter(env, self);
@@ -1089,17 +1123,19 @@
::GlobalUnlock(devnames);
if (devLandRotation == 270) {
- setBooleanField(env, self, LANDSCAPE_270_STR, JNI_TRUE);
+ err = setBooleanField(env, self, LANDSCAPE_270_STR, JNI_TRUE);
} else {
- setBooleanField(env, self, LANDSCAPE_270_STR, JNI_FALSE);
+ err = setBooleanField(env, self, LANDSCAPE_270_STR, JNI_FALSE);
}
+ if (err) return;
}
if (dmFields & DM_COLLATE) {
- setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_TRUE);
+ err = setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_TRUE);
} else {
- setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE);
+ err = setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE);
}
+ if (err) return;
if (dmFields & DM_COPIES) {
setBooleanField(env, self, DRIVER_COPIES_STR, JNI_TRUE);
@@ -1110,39 +1146,54 @@
}
-static bool setPrintReqAttribute(JNIEnv *env, jobject self, DEVMODE* devmode) {
+/*
+ * returns 0 if print capabilities has been changed
+ * 1 if print capabilities has not been changed
+ * -1 in case of error
+ */
+static int setPrintReqAttribute(JNIEnv *env, jobject self, DEVMODE* devmode) {
/* The xRes/yRes fields are only initialised if there is a resolution
* attribute. Otherwise they both will be zero, in which case default
* resolution should be fine. Consider calling getXRes()/getResY()
* rather than accessing the fields directly
*/
- int xRes=getIntField(env, self, ATTXRES_STR);
- int yRes=getIntField(env, self, ATTYRES_STR);
- int quality=getIntField(env, self, ATTQUALITY_STR);
- int printColor = getIntField(env, self, ATTCHROMATICITY_STR);
- int sides = getIntField(env, self, ATTSIDES_STR);
- int collate = getIntField(env, self, ATTCOLLATE_STR);
+ jboolean err;
+ int xRes=getIntField(env, &err, self, ATTXRES_STR);
+ if (err) return -1;
+ int yRes=getIntField(env, &err, self, ATTYRES_STR);
+ if (err) return -1;
+ int quality=getIntField(env, &err, self, ATTQUALITY_STR);
+ if (err) return -1;
+ int printColor = getIntField(env, &err, self, ATTCHROMATICITY_STR);
+ if (err) return -1;
+ int sides = getIntField(env, &err, self, ATTSIDES_STR);
+ if (err) return -1;
+ int collate = getIntField(env, &err, self, ATTCOLLATE_STR);
+ if (err) return -1;
int copies = 1;
- jclass myClass = env->GetObjectClass(self);
// There may be cases when driver reports it cannot handle
// multiple copies although it actually can . So this modification
// handles that, to make sure that we report copies = 1 because
// we already emulated multiple copies.
- jfieldID fieldId = env->GetFieldID(myClass, DRIVER_COPIES_STR, "Z");
- if (env->GetBooleanField(self, fieldId)) {
- copies = getIntField(env, self, ATTCOPIES_STR);
+ jboolean driverHandlesCopies = getBooleanField(env, &err, self, DRIVER_COPIES_STR);
+ if (err) return -1;
+ if (driverHandlesCopies) {
+ copies = getIntField(env, &err, self, ATTCOPIES_STR);
+ if (err) return -1;
} // else "driverDoesMultipleCopies" is false, copies should be 1 (default)
- int mediatray = getIntField(env, self, ATTMEDIATRAY_STR);
- int mediaszname = getIntField(env, self, ATTMEDIASZNAME_STR);
- bool ret = true;
+ int mediatray = getIntField(env, &err, self, ATTMEDIATRAY_STR);
+ if (err) return -1;
+ int mediaszname = getIntField(env, &err, self, ATTMEDIASZNAME_STR);
+ if (err) return -1;
+ int ret = 1;
if (quality && quality < 0) {
if (quality != devmode->dmPrintQuality) {
devmode->dmPrintQuality = quality;
devmode->dmFields |= DM_PRINTQUALITY;
- // ret of "false" means that setCapabilities needs to be called
- ret = false;
+ // ret of 0 means that setCapabilities needs to be called
+ ret = 0;
}
} else {
/* If we didn't set quality, maybe we have resolution settings. */
@@ -1256,7 +1307,7 @@
if (port != NULL && isFilePort(port)) {
LPTSTR defPort = GetPrinterPort(env, printer);
if (!isFilePort(defPort)) { // not a FILE: port by default
- int len = wcslen(defPort);
+ size_t len = wcslen(defPort);
if (len > 0 && port[len-1] == L':') { // is a device port
dest = defPort;
} else {
@@ -1291,12 +1342,19 @@
LPTSTR destination = NULL;
if (dest != NULL) {
destination = (LPTSTR)JNU_GetStringPlatformChars(env, dest, NULL);
+ CHECK_NULL_RETURN(destination, JNI_FALSE);
} else {
destination = VerifyDestination(env, self);
}
LPTSTR docname = NULL;
if (jobname != NULL) {
LPTSTR tmp = (LPTSTR)JNU_GetStringPlatformChars(env, jobname, NULL);
+ if (tmp == NULL) {
+ if (dest != NULL) {
+ JNU_ReleaseStringPlatformChars(env, dest, destination);
+ }
+ return JNI_FALSE;
+ }
docname = _tcsdup(tmp);
JNU_ReleaseStringPlatformChars(env, jobname, tmp);
} else {
@@ -1317,23 +1375,33 @@
HGLOBAL hDevMode = AwtPrintControl::getPrintHDMode(env, self);
if (printDC != NULL && hDevMode != NULL) {
DEVMODE *devmode = (DEVMODE *)::GlobalLock(hDevMode);
+ bool success = true;
if (devmode != NULL) {
devmode->dmFields |= DM_ORIENTATION;
devmode->dmOrientation = DMORIENT_PORTRAIT;
/* set attribute values into devmode */
- bool ret = setPrintReqAttribute(env, self, devmode);
+ int ret = setPrintReqAttribute(env, self, devmode);
::ResetDC(printDC, devmode);
RESTORE_CONTROLWORD
- if (!ret) {
+ if (ret == 0) {
/*
Need to read in updated device capabilities because
print quality has been changed.
*/
setCapabilities(env, self, printDC);
+ if (env->ExceptionCheck()) success = false;
+ } else if (ret < 0) {
+ success = false;
}
}
::GlobalUnlock(hDevMode);
+ if (!success) {
+ if (dest != NULL) {
+ JNU_ReleaseStringPlatformChars(env, dest, destination);
+ }
+ return JNI_FALSE;
+ }
}
if (printDC){
@@ -1358,13 +1426,13 @@
} else {
err = 0;
}
- if (dest != NULL) {
- JNU_ReleaseStringPlatformChars(env, dest, destination);
- }
}
else {
- jclass printerException = env->FindClass(PRINTEREXCEPTION_STR);
- env->ThrowNew(printerException, "No printer found.");
+ JNU_ThrowByName(env, PRINTEREXCEPTION_STR, "No printer found.");
+ }
+
+ if (dest != NULL) {
+ JNU_ReleaseStringPlatformChars(env, dest, destination);
}
if (err && err != ERROR_CANCELLED) {
@@ -1481,7 +1549,9 @@
LONG retval = 0;
HGLOBAL hDevMode = AwtPrintControl::getPrintHDMode(env, self);
HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, self);
- WORD dmPaperSize = getPrintPaperSize(env, self);
+ jboolean err;
+ WORD dmPaperSize = getPrintPaperSize(env, &err, self);
+ if (err) return;
SAVE_CONTROLWORD
// Unless the PageFormat has been changed, do not set the paper
// size for a new page. Doing so is unnecessary, perhaps expensive,
@@ -1492,7 +1562,9 @@
RectDouble paperSize;
RectDouble margins;
jobject paper = getPaper(env, format);
+ CHECK_NULL(paper);
getPaperValues(env, paper, &paperSize, &margins);
+ JNU_CHECK_EXCEPTION(env);
double paperWidth, paperHeight;
matchPaperSize(printDC, hDevMode, hDevNames,
paperSize.width, paperSize.height,
@@ -1656,6 +1728,7 @@
jbyte *image = NULL;
try {
image = (jbyte *)env->GetPrimitiveArrayCritical(imageArray, 0);
+ CHECK_NULL(image);
struct {
BITMAPINFOHEADER bmiHeader;
DWORD* bmiColors;
@@ -2194,6 +2267,7 @@
memset(&matchedLogFont, 0, sizeof(matchedLogFont));
LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL);
+ CHECK_NULL_RETURN(fontNameW, JNI_FALSE);
/* Describe the GDI fonts we want enumerated. We
* simply supply the java font name and let GDI
@@ -2383,6 +2457,7 @@
{
SIZE size;
LPCWSTR wText = JNU_GetStringPlatformChars(env, text, NULL);
+ CHECK_NULL_RETURN(wText, 0);
size_t strLen = wcslen(wText);
BOOL ok = GetTextExtentPoint32((HDC)printDC, wText, (int)strLen, &size);
JNU_ReleaseStringPlatformChars(env, text, wText);
@@ -2438,6 +2513,7 @@
long posY = ROUND_TO_LONG(y);
int flags = (glyphCodes !=0) ? ETO_GLYPH_INDEX : 0;
LPCWSTR wText = JNU_GetStringPlatformChars(env, text, NULL);
+ CHECK_NULL(wText);
int *advances = NULL, *xadvances = NULL, *xyadvances = NULL;
BOOL useYAdvances = FALSE;
@@ -2841,10 +2917,12 @@
numCols = MAXCOLS; /* don't write past end of struct */
}
bmiCols = (BYTE*)env->GetPrimitiveArrayCritical(bmiColorsArray, 0);
+ CHECK_NULL(bmiCols);
memcpy(&(bmi.bmiColors[0]), bmiCols, (numCols*4));
env->ReleasePrimitiveArrayCritical(bmiColorsArray, bmiCols, 0);
}
imageBits = (jint *)env->GetPrimitiveArrayCritical(image, 0);
+ CHECK_NULL(imageBits);
// Workaround for drivers/apps that do not support top-down.
// Because we don't know if they support or not,
@@ -2900,6 +2978,7 @@
try {
long scanLineStride = J2DRasterBPP * width;
image = (jbyte *)env->GetPrimitiveArrayCritical(imageArray, 0);
+ CHECK_NULL(image);
jbyte *startImage;
jbyte *endImage = NULL;
long startY = 0;
@@ -3132,6 +3211,9 @@
*/
int maxCopies = 1;
int nCopies = getCopies(env, printerJob);
+ if (nCopies < 0) {
+ return NULL;
+ }
SAVE_CONTROLWORD
if (pd.hDevNames != NULL) {
DEVNAMES *devnames = (DEVNAMES *)::GlobalLock(pd.hDevNames);
@@ -3176,11 +3258,14 @@
AwtPrintControl::setPrintHDName(env, printerJob, pd.hDevNames);
}
- setBooleanField(env, printerJob, DRIVER_COPIES_STR,
- (devWillDoCopies ? JNI_TRUE : JNI_FALSE));
- setBooleanField(env, printerJob, DRIVER_COLLATE_STR, JNI_FALSE);
- setBooleanField(env, printerJob, USER_COLLATE_STR, JNI_FALSE);
-
+ jboolean err;
+ err = setBooleanField(env, printerJob, DRIVER_COPIES_STR,
+ (devWillDoCopies ? JNI_TRUE : JNI_FALSE));
+ if (err) return NULL;
+ err = setBooleanField(env, printerJob, DRIVER_COLLATE_STR, JNI_FALSE);
+ if (err) return NULL;
+ err = setBooleanField(env, printerJob, USER_COLLATE_STR, JNI_FALSE);
+ if (err) return NULL;
}
return printDC;
@@ -3200,6 +3285,7 @@
/* Move the orientation from PageFormat to Windows.
*/
jint orient = getPageFormatOrientation(env, page);
+ if (orient < 0) return;
int gdiOrientation = (orient == PAGEFORMAT_PORTRAIT) ?
DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE;
setOrientationInDevMode(setup->hDevMode, orient == PAGEFORMAT_PORTRAIT);
@@ -3208,7 +3294,9 @@
? MM_HIENGLISH
: MM_HIMETRIC;
jobject paper = getPaper(env, page);
+ CHECK_NULL(paper);
getPaperValues(env, paper, &paperSize, &margins);
+ JNU_CHECK_EXCEPTION(env);
// Setting the paper size appears to be a futile exercise, as its not one
// of the values you can initialise - its an out-only arg. Margins are OK.
// set it into the DEVMODE if there is one ..
@@ -3218,7 +3306,9 @@
if (setup->hDevMode != NULL) {
double paperWidth, paperHeight;
- WORD dmPaperSize = getPrintPaperSize(env, job);
+ jboolean err;
+ WORD dmPaperSize = getPrintPaperSize(env, &err, job);
+ if (err) return;
matchPaperSize(hDC, setup->hDevMode, setup->hDevNames,
paperSize.width, paperSize.height,
&paperWidth, &paperHeight, &dmPaperSize);
@@ -3444,6 +3534,7 @@
jclass printerJobClass = env->GetObjectClass(printerJob);
jmethodID getCopiesID = env->GetMethodID(printerJobClass, GETCOPIES_STR,
GETCOPIES_SIG);
+ CHECK_NULL_RETURN(getCopiesID, -1);
jint copies = env->CallIntMethod(printerJob, getCopiesID);
return copies;
@@ -3462,6 +3553,7 @@
jclass pageClass = env->GetObjectClass(page);
jmethodID getPaperID = env->GetMethodID(pageClass, GETPAPER_STR,
GETPAPER_SIG);
+ CHECK_NULL_RETURN(getPaperID, NULL);
return env->CallObjectMethod(page, getPaperID);
}
@@ -3479,12 +3571,14 @@
jclass pageClass = env->GetObjectClass(page);
jmethodID setPaperID = env->GetMethodID(pageClass, SETPAPER_STR,
SETPAPER_SIG);
+ CHECK_NULL(setPaperID);
env->CallVoidMethod(page, setPaperID, paper);
}
/**
* Return the integer ID for the orientation in the PageFormat.
* Caution: this is the Java spec ID, not the GDI ID.
+ * In case of error returns -1
*/
static jint getPageFormatOrientation(JNIEnv *env, jobject page) {
// Because this function may call client Java code,
@@ -3494,6 +3588,7 @@
jclass pageClass = env->GetObjectClass(page);
jmethodID getOrientID = env->GetMethodID(pageClass, GETORIENT_STR,
GETORIENT_SIG);
+ CHECK_NULL_RETURN(getOrientID, -1);
return env->CallIntMethod(page, getOrientID);
}
@@ -3506,6 +3601,7 @@
jclass pageClass = env->GetObjectClass(page);
jmethodID setOrientID = env->GetMethodID(pageClass, SETORIENT_STR,
SETORIENT_SIG);
+ CHECK_NULL(setOrientID);
env->CallVoidMethod(page, setOrientID, orientation);
}
@@ -3527,24 +3623,29 @@
jclass paperClass = env->GetObjectClass(paper);
getID = env->GetMethodID(paperClass, GETWIDTH_STR, GETWIDTH_SIG);
+ CHECK_NULL(getID);
paperSize->width = env->CallDoubleMethod(paper, getID);
getID = env->GetMethodID(paperClass, GETHEIGHT_STR, GETHEIGHT_SIG);
+ CHECK_NULL(getID);
paperSize->height = env->CallDoubleMethod(paper, getID);
getID = env->GetMethodID(paperClass, GETIMG_X_STR, GETIMG_X_SIG);
+ CHECK_NULL(getID);
margins->x = env->CallDoubleMethod(paper, getID);
if (margins-> x < 0 ) {
margins-> x = 0;
}
getID = env->GetMethodID(paperClass, GETIMG_Y_STR, GETIMG_Y_SIG);
+ CHECK_NULL(getID);
margins->y = env->CallDoubleMethod(paper, getID);
if (margins-> y < 0 ) {
margins-> y = 0;
}
getID = env->GetMethodID(paperClass, GETIMG_W_STR, GETIMG_W_SIG);
+ CHECK_NULL(getID);
if (widthAsMargin) {
margins->width = paperSize->width - margins->x
- env->CallDoubleMethod(paper, getID);
@@ -3557,6 +3658,7 @@
}
getID = env->GetMethodID(paperClass, GETIMG_H_STR, GETIMG_H_SIG);
+ CHECK_NULL(getID);
if (widthAsMargin) {
margins->height = paperSize->height - margins->y
- env->CallDoubleMethod(paper, getID);
@@ -3567,7 +3669,6 @@
if (margins->height < 0) {
margins->height = 0;
}
-
}
/**
@@ -3587,8 +3688,10 @@
jclass paperClass = env->GetObjectClass(paper);
jmethodID setSizeID = env->GetMethodID(paperClass,
SETSIZE_STR, SETSIZE_SIG);
+ CHECK_NULL(setSizeID);
jmethodID setImageableID = env->GetMethodID(paperClass,
SETIMAGEABLE_STR, SETIMAGEABLE_SIG);
+ CHECK_NULL(setImageableID);
/* Set the physical size of the paper.
*/
@@ -3608,7 +3711,6 @@
jdouble width = convertToPoints(intWidth, units);
jdouble height = convertToPoints(intHeight, units);
env->CallVoidMethod(paper, setImageableID, x, y, width, height);
-
}
/**
@@ -3682,13 +3784,16 @@
*/
void setCapabilities(JNIEnv *env, jobject self, HDC printDC) {
+ jboolean err;
// width of page in pixels
jint pageWid = GetDeviceCaps(printDC, PHYSICALWIDTH);
- setIntField(env, self, PAGEW_STR, pageWid);
+ err = setIntField(env, self, PAGEW_STR, pageWid);
+ if (err) return;
// height of page in pixels
jint pageHgt = GetDeviceCaps(printDC, PHYSICALHEIGHT);
- setIntField(env, self, PAGEH_STR, pageHgt);
+ err = setIntField(env, self, PAGEH_STR, pageHgt);
+ if (err) return;
// x scaling factor of printer
jint xsf = GetDeviceCaps(printDC, SCALINGFACTORX);
@@ -3716,111 +3821,67 @@
// pixels per inch in x direction
jint xRes = GetDeviceCaps(printDC, LOGPIXELSX);
- setIntField(env, self, XRES_STR, xRes);
+ err = setIntField(env, self, XRES_STR, xRes);
+ if (err) return;
// pixels per inch in y direction
jint yRes = GetDeviceCaps(printDC, LOGPIXELSY);
- setIntField(env, self, YRES_STR, yRes);
+ err = setIntField(env, self, YRES_STR, yRes);
// x coord of printable area in pixels
jint xOrg = GetDeviceCaps(printDC, PHYSICALOFFSETX);
- setIntField(env, self, PHYSX_STR, xOrg);
+ err = setIntField(env, self, PHYSX_STR, xOrg);
+ if (err) return;
// y coord of printable area in pixels
jint yOrg = GetDeviceCaps(printDC, PHYSICALOFFSETY);
- setIntField(env, self, PHYSY_STR, yOrg);
+ err = setIntField(env, self, PHYSY_STR, yOrg);
+ if (err) return;
// width of printable area in pixels
jint printWid = GetDeviceCaps(printDC, HORZRES);
- setIntField(env, self, PHYSW_STR, printWid);
+ err = setIntField(env, self, PHYSW_STR, printWid);
+ if (err) return;
// height of printable area in pixels
jint printHgt = GetDeviceCaps(printDC, VERTRES);
setIntField(env, self, PHYSH_STR, printHgt);
-
}
-
-static inline WORD getPrintPaperSize(JNIEnv *env, jobject self) {
- return (WORD)getIntField(env, self, PRINTPAPERSIZE_STR);
+static inline WORD getPrintPaperSize(JNIEnv *env, jboolean* err, jobject self) {
+ return (WORD)getIntField(env, err, self, PRINTPAPERSIZE_STR);
}
-static inline void setPrintPaperSize(JNIEnv *env, jobject self, WORD sz) {
- setIntField(env, self, PRINTPAPERSIZE_STR, (jint)sz);
+static inline jboolean setPrintPaperSize(JNIEnv *env, jobject self, WORD sz) {
+ return setIntField(env, self, PRINTPAPERSIZE_STR, (jint)sz);
}
/**
* Return the java int value of the field 'fieldName' in the
* java instance 'self'.
*/
-static jint getIntField(JNIEnv *env, jobject self, const char *fieldName) {
- jfieldID fieldId = getIdOfIntField(env, self, fieldName);
- return env->GetIntField(self, fieldId);
-}
-
-/**
- * Return the java long value of the field 'fieldName' in the
- * java instance 'self'.
- */
-static jlong getLongField(JNIEnv *env, jobject self, const char *fieldName) {
- jfieldID fieldId = getIdOfLongField(env, self, fieldName);
- return env->GetLongField(self, fieldId);
+static jint getIntField(JNIEnv *env, jboolean* err, jobject self, const char *fieldName) {
+ return JNU_GetFieldByName(env, err, self, fieldName, "I").i;
}
/**
* Set the int field named 'fieldName' of the java instance
* 'self' to the value 'value'.
*/
-static void setIntField(JNIEnv *env, jobject self, const char *fieldName,
- jint value) {
- jfieldID fieldId = getIdOfIntField(env, self, fieldName);
- env->SetIntField(self, fieldId, value);
+static jboolean setIntField(JNIEnv *env, jobject self, const char *fieldName, jint value) {
+ jboolean err;
+ JNU_SetFieldByName(env, &err, self, fieldName, "I", value);
+ return err;
}
-/**
- * Set the long field named 'fieldName' of the java instance
- * 'self' to the value 'value'.
- */
-static void setLongField(JNIEnv *env, jobject self, const char *fieldName,
- jlong value) {
- jfieldID fieldId = getIdOfLongField(env, self, fieldName);
- env->SetLongField(self, fieldId, value);
+static jboolean getBooleanField(JNIEnv *env, jboolean* err, jobject self, const char *fieldName) {
+ return JNU_GetFieldByName(env, err, self, fieldName, "Z").z;
}
-/**
- * Return the field id of the java instance 'self' of the
- * java int field named 'fieldName'.
- */
-static jfieldID getIdOfIntField(JNIEnv *env, jobject self,
- const char *fieldName) {
- jclass myClass = env->GetObjectClass(self);
- jfieldID fieldId = env->GetFieldID(myClass, fieldName, kJavaIntStr);
- DASSERT(fieldId != 0);
-
- return fieldId;
-
-}
-
-/**
- * Return the field id of the java instance 'self' of the
- * java long field named 'fieldName'.
- */
-static jfieldID getIdOfLongField(JNIEnv *env, jobject self,
- const char *fieldName) {
- jclass myClass = env->GetObjectClass(self);
- jfieldID fieldId = env->GetFieldID(myClass, fieldName, kJavaLongStr);
- DASSERT(fieldId != 0);
-
- return fieldId;
-
-}
-
-static void setBooleanField(JNIEnv *env, jobject self, const char *fieldName,
- jboolean value) {
- jclass myClass = env->GetObjectClass(self);
- jfieldID fieldId = env->GetFieldID(myClass, fieldName, "Z");
- DASSERT(fieldId != 0);
- env->SetBooleanField(self, fieldId, value);
+static jboolean setBooleanField(JNIEnv *env, jobject self, const char *fieldName, jboolean value) {
+ jboolean err;
+ JNU_SetFieldByName(env, &err, self, fieldName, "Z", value);
+ return err;
}
/**
@@ -3830,8 +3891,6 @@
static void throwPrinterException(JNIEnv *env, DWORD err) {
char errStr[256];
TCHAR t_errStr[256];
- jclass printerException = env->FindClass(PRINTEREXCEPTION_STR);
-
errStr[0] = '\0';
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
@@ -3843,7 +3902,7 @@
WideCharToMultiByte(CP_UTF8, 0, t_errStr, -1,
errStr, sizeof(errStr), NULL, NULL);
- env->ThrowNew(printerException, errStr);
+ JNU_ThrowByName(env, PRINTEREXCEPTION_STR, errStr);
}
@@ -4176,8 +4235,9 @@
jstring printer)
{
TRY;
- LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env,
- printer, NULL);
+ LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
+ CHECK_NULL(printerName);
+
HDC hDC = AwtPrintControl::getPrintDC(env, name);
if (hDC != NULL) {
DeletePrintDC(hDC);
@@ -4188,8 +4248,7 @@
hDC = ::CreateDC(TEXT("WINSPOOL"), printerName, NULL, NULL);
RESTORE_CONTROLWORD
if (hDC == NULL) {
- jclass printerException = env->FindClass(PRINTEREXCEPTION_STR);
- env->ThrowNew(printerException, "Invalid name of PrintService.");
+ JNU_ThrowByName(env, PRINTEREXCEPTION_STR, "Invalid name of PrintService.");
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return;
}
@@ -4223,11 +4282,19 @@
if (devmode != NULL) {
if (devmode->dmFields & DM_COPIES) {
- setBooleanField(env, name, DRIVER_COPIES_STR, JNI_TRUE);
+ jboolean err = setBooleanField(env, name, DRIVER_COPIES_STR, JNI_TRUE);
+ if (err) {
+ JNU_ReleaseStringPlatformChars(env, printer, printerName);
+ return;
+ }
}
if (devmode->dmFields & DM_COLLATE) {
- setBooleanField(env, name, DRIVER_COLLATE_STR, JNI_TRUE);
+ jboolean err = setBooleanField(env, name, DRIVER_COLLATE_STR, JNI_TRUE);
+ if (err) {
+ JNU_ReleaseStringPlatformChars(env, printer, printerName);
+ return;
+ }
}
::GlobalUnlock(hDevMode);
@@ -4237,7 +4304,6 @@
JNU_ReleaseStringPlatformChars(env, printer, printerName);
CATCH_BAD_ALLOC;
-
}
@@ -4299,14 +4365,15 @@
{
TRY;
- AwtPrintDialog::controlID =
- env->GetFieldID(cls, "pjob", "Ljava/awt/print/PrinterJob;");
- jclass printDialogPeerClass = env->FindClass("sun/awt/windows/WPrintDialogPeer");
- AwtPrintDialog::setHWndMID =
- env->GetMethodID(printDialogPeerClass, "setHWnd", "(J)V");
-
+ AwtPrintDialog::controlID = env->GetFieldID(cls, "pjob", "Ljava/awt/print/PrinterJob;");
DASSERT(AwtPrintDialog::controlID != NULL);
+ CHECK_NULL(AwtPrintDialog::controlID);
+
+ jclass printDialogPeerClass = env->FindClass("sun/awt/windows/WPrintDialogPeer");
+ CHECK_NULL(printDialogPeerClass);
+ AwtPrintDialog::setHWndMID = env->GetMethodID(printDialogPeerClass, "setHWnd", "(J)V");
DASSERT(AwtPrintDialog::setHWndMID != NULL);
+ CHECK_NULL(AwtPrintDialog::setHWndMID);
AwtPrintControl::initIDs(env, cls);
CATCH_BAD_ALLOC;
diff --git a/jdk/src/windows/native/sun/windows/awt_Rectangle.cpp b/jdk/src/windows/native/sun/windows/awt_Rectangle.cpp
index 59f4c48..07ec535 100644
--- a/jdk/src/windows/native/sun/windows/awt_Rectangle.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Rectangle.cpp
@@ -46,14 +46,20 @@
TRY;
AwtRectangle::xID = env->GetFieldID(cls, "x", "I");
- AwtRectangle::yID = env->GetFieldID(cls, "y", "I");
- AwtRectangle::widthID = env->GetFieldID(cls, "width", "I");
- AwtRectangle::heightID = env->GetFieldID(cls, "height", "I");
-
DASSERT(AwtRectangle::xID != NULL);
+ CHECK_NULL(AwtRectangle::xID);
+
+ AwtRectangle::yID = env->GetFieldID(cls, "y", "I");
DASSERT(AwtRectangle::yID != NULL);
+ CHECK_NULL(AwtRectangle::yID);
+
+ AwtRectangle::widthID = env->GetFieldID(cls, "width", "I");
DASSERT(AwtRectangle::widthID != NULL);
+ CHECK_NULL(AwtRectangle::widthID);
+
+ AwtRectangle::heightID = env->GetFieldID(cls, "height", "I");
DASSERT(AwtRectangle::heightID != NULL);
+ CHECK_NULL(AwtRectangle::heightID);
CATCH_BAD_ALLOC;
}
diff --git a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp
index c5750fa..d96a194 100644
--- a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp
@@ -852,9 +852,10 @@
TRY;
jclass textComponentClassID = env->FindClass("java/awt/TextComponent");
+ CHECK_NULL(textComponentClassID);
+
AwtTextComponent::canAccessClipboardMID =
- env->GetMethodID(textComponentClassID,
- "canAccessClipboard", "()Z");
+ env->GetMethodID(textComponentClassID, "canAccessClipboard", "()Z");
env->DeleteLocalRef(textComponentClassID);
DASSERT(AwtTextComponent::canAccessClipboardMID != NULL);
diff --git a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp
index ba8d6de..2ef0f0c 100644
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -172,35 +172,22 @@
if (awtAutoShutdownClass == NULL) {
jclass awtAutoShutdownClassLocal = env->FindClass("sun/awt/AWTAutoShutdown");
- if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
DASSERT(awtAutoShutdownClassLocal != NULL);
- if (awtAutoShutdownClassLocal == NULL) {
- return;
- }
+ if (!awtAutoShutdownClassLocal) throw std::bad_alloc();
awtAutoShutdownClass = (jclass)env->NewGlobalRef(awtAutoShutdownClassLocal);
env->DeleteLocalRef(awtAutoShutdownClassLocal);
+ if (!awtAutoShutdownClass) throw std::bad_alloc();
notifyBusyMethodID = env->GetStaticMethodID(awtAutoShutdownClass,
"notifyToolkitThreadBusy", "()V");
- if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
+ DASSERT(notifyBusyMethodID != NULL);
+ if (!notifyBusyMethodID) throw std::bad_alloc();
+
notifyFreeMethodID = env->GetStaticMethodID(awtAutoShutdownClass,
"notifyToolkitThreadFree", "()V");
- if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- DASSERT(notifyBusyMethodID != NULL);
DASSERT(notifyFreeMethodID != NULL);
- if (notifyBusyMethodID == NULL || notifyFreeMethodID == NULL) {
- return;
- }
+ if (!notifyFreeMethodID) throw std::bad_alloc();
} /* awtAutoShutdownClass == NULL*/
if (busy) {
@@ -776,9 +763,11 @@
jclass systemColorClass = env->FindClass("java/awt/SystemColor");
DASSERT(systemColorClass);
+ if (!systemColorClass) throw std::bad_alloc();
jmethodID mid = env->GetStaticMethodID(systemColorClass, "updateSystemColors", "()V");
DASSERT(mid);
+ if (!mid) throw std::bad_alloc();
env->CallStaticVoidMethod(systemColorClass, mid);
@@ -1038,6 +1027,8 @@
// Notify Java side - call WToolkit.displayChanged()
jclass clazz = env->FindClass("sun/awt/windows/WToolkit");
+ DASSERT(clazz != NULL);
+ if (!clazz) throw std::bad_alloc();
env->CallStaticVoidMethod(clazz, AwtToolkit::displayChangeMID);
GetInstance().m_displayChanged = TRUE;
@@ -2050,15 +2041,20 @@
AwtToolkit::getDefaultToolkitMID =
env->GetStaticMethodID(cls,"getDefaultToolkit","()Ljava/awt/Toolkit;");
- AwtToolkit::getFontMetricsMID =
- env->GetMethodID(cls, "getFontMetrics",
- "(Ljava/awt/Font;)Ljava/awt/FontMetrics;");
- AwtToolkit::insetsMID =
- env->GetMethodID(env->FindClass("java/awt/Insets"), "<init>", "(IIII)V");
-
DASSERT(AwtToolkit::getDefaultToolkitMID != NULL);
+ CHECK_NULL(AwtToolkit::getDefaultToolkitMID);
+
+ AwtToolkit::getFontMetricsMID =
+ env->GetMethodID(cls, "getFontMetrics", "(Ljava/awt/Font;)Ljava/awt/FontMetrics;");
DASSERT(AwtToolkit::getFontMetricsMID != NULL);
- DASSERT(AwtToolkit::insetsMID != NULL);
+ CHECK_NULL(AwtToolkit::getFontMetricsMID);
+
+ jclass insetsClass = env->FindClass("java/awt/Insets");
+ DASSERT(insetsClass != NULL);
+ CHECK_NULL(insetsClass);
+ AwtToolkit::insetsMID = env->GetMethodID(insetsClass, "<init>", "(IIII)V");
+ DASSERT(AwtToolkit::insetsMID != NULL);
+ CHECK_NULL(AwtToolkit::insetsMID);
CATCH_BAD_ALLOC;
}
@@ -2085,10 +2081,12 @@
AwtToolkit::windowsSettingChangeMID =
env->GetMethodID(cls, "windowsSettingChange", "()V");
DASSERT(AwtToolkit::windowsSettingChangeMID != 0);
+ CHECK_NULL(AwtToolkit::windowsSettingChangeMID);
AwtToolkit::displayChangeMID =
env->GetStaticMethodID(cls, "displayChanged", "()V");
DASSERT(AwtToolkit::displayChangeMID != 0);
+ CHECK_NULL(AwtToolkit::displayChangeMID);
// Set various global IDs needed by JAWT code. Note: these
// variables cannot be set by JAWT code directly due to
@@ -2099,24 +2097,37 @@
// negligible penalty.
jclass sDataClassLocal = env->FindClass("sun/java2d/SurfaceData");
DASSERT(sDataClassLocal != 0);
+ CHECK_NULL(sDataClassLocal);
+
jclass vImgClassLocal = env->FindClass("sun/awt/image/SunVolatileImage");
DASSERT(vImgClassLocal != 0);
+ CHECK_NULL(vImgClassLocal);
+
jclass vSMgrClassLocal =
env->FindClass("sun/awt/image/VolatileSurfaceManager");
DASSERT(vSMgrClassLocal != 0);
+ CHECK_NULL(vSMgrClassLocal);
+
jclass componentClassLocal = env->FindClass("java/awt/Component");
DASSERT(componentClassLocal != 0);
+ CHECK_NULL(componentClassLocal);
+
jawtSMgrID = env->GetFieldID(vImgClassLocal, "volSurfaceManager",
"Lsun/awt/image/VolatileSurfaceManager;");
DASSERT(jawtSMgrID != 0);
+ CHECK_NULL(jawtSMgrID);
+
jawtSDataID = env->GetFieldID(vSMgrClassLocal, "sdCurrent",
"Lsun/java2d/SurfaceData;");
DASSERT(jawtSDataID != 0);
+ CHECK_NULL(jawtSDataID);
+
jawtPDataID = env->GetFieldID(sDataClassLocal, "pData", "J");
DASSERT(jawtPDataID != 0);
-
+ CHECK_NULL(jawtPDataID);
// Save these classes in global references for later use
jawtVImgClass = (jclass)env->NewGlobalRef(vImgClassLocal);
+ CHECK_NULL(jawtVImgClass);
jawtComponentClass = (jclass)env->NewGlobalRef(componentClassLocal);
CATCH_BAD_ALLOC;
@@ -2377,7 +2388,11 @@
TRY;
if (AwtToolkit::GetScreenInsets(screen, &rect)) {
- insets = env->NewObject(env->FindClass("java/awt/Insets"),
+ jclass insetsClass = env->FindClass("java/awt/Insets");
+ DASSERT(insetsClass != NULL);
+ CHECK_NULL_RETURN(insetsClass, NULL);
+
+ insets = env->NewObject(insetsClass,
AwtToolkit::insetsMID,
rect.top,
rect.left,
diff --git a/jdk/src/windows/native/sun/windows/awt_Toolkit.h b/jdk/src/windows/native/sun/windows/awt_Toolkit.h
index 5ee5e49..3782aac 100644
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -80,7 +80,7 @@
int result = m_env->PushLocalFrame(size);
if (result < 0) {
DASSERT(FALSE);
- JNU_ThrowOutOfMemoryError(m_env, "Can't allocate localRefs");
+ throw std::bad_alloc();
}
}
INLINE ~JNILocalFrame() { m_env->PopLocalFrame(NULL); }
diff --git a/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp b/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp
index c26769b..d453101 100644
--- a/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, 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
@@ -503,6 +503,7 @@
env->GetMethodID(mouseEventCls, "<init>",
"(Ljava/awt/Component;IJIIIIIIZI)V");
DASSERT(mouseEventConst);
+ CHECK_NULL(mouseEventConst);
}
if (env->EnsureLocalCapacity(2) < 0) {
return;
@@ -556,6 +557,7 @@
env->GetMethodID(actionEventCls, "<init>",
"(Ljava/lang/Object;ILjava/lang/String;JI)V");
DASSERT(actionEventConst);
+ CHECK_NULL(actionEventConst);
}
if (env->EnsureLocalCapacity(2) < 0) {
return;
@@ -736,6 +738,7 @@
}
tooltipStr = JNU_GetStringPlatformChars(env, jtooltip, (jboolean *)NULL);
+ if (env->ExceptionCheck()) goto ret;
trayIcon->SetToolTip(tooltipStr);
JNU_ReleaseStringPlatformChars(env, jtooltip, tooltipStr);
ret:
@@ -855,9 +858,18 @@
trayIcon = (AwtTrayIcon *)pData;
captionStr = JNU_GetStringPlatformChars(env, jcaption, (jboolean *)NULL);
+ if (env->ExceptionCheck()) goto ret;
textStr = JNU_GetStringPlatformChars(env, jtext, (jboolean *)NULL);
+ if (env->ExceptionCheck()) {
+ JNU_ReleaseStringPlatformChars(env, jcaption, captionStr);
+ goto ret;
+ }
msgTypeStr = JNU_GetStringPlatformChars(env, jmsgType, (jboolean *)NULL);
-
+ if (env->ExceptionCheck()) {
+ JNU_ReleaseStringPlatformChars(env, jcaption, captionStr);
+ JNU_ReleaseStringPlatformChars(env, jtext, textStr);
+ goto ret;
+ }
trayIcon->DisplayMessage(captionStr, textStr, msgTypeStr);
JNU_ReleaseStringPlatformChars(env, jcaption, captionStr);
@@ -889,10 +901,12 @@
/* init field ids */
AwtTrayIcon::idID = env->GetFieldID(cls, "id", "I");
- AwtTrayIcon::actionCommandID = env->GetFieldID(cls, "actionCommand", "Ljava/lang/String;");
-
DASSERT(AwtTrayIcon::idID != NULL);
+ CHECK_NULL(AwtTrayIcon::idID);
+
+ AwtTrayIcon::actionCommandID = env->GetFieldID(cls, "actionCommand", "Ljava/lang/String;");
DASSERT(AwtTrayIcon::actionCommandID != NULL);
+ CHECK_NULL( AwtTrayIcon::actionCommandID);
CATCH_BAD_ALLOC;
}
@@ -981,8 +995,11 @@
jint *intRasterDataPtr = NULL;
HBITMAP hColor = NULL;
try {
- intRasterDataPtr =
- (jint *)env->GetPrimitiveArrayCritical(intRasterData, 0);
+ intRasterDataPtr = (jint *)env->GetPrimitiveArrayCritical(intRasterData, 0);
+ if (intRasterDataPtr == NULL) {
+ ::DeleteObject(hMask);
+ return;
+ }
hColor = AwtTrayIcon::CreateBMP(NULL, (int *)intRasterDataPtr, nSS, nW, nH);
} catch (...) {
if (intRasterDataPtr != NULL) {
diff --git a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp
index 3d678b5..918ed08 100644
--- a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -91,6 +91,7 @@
jobject bounds = NULL;
clazz = env->FindClass("java/awt/Rectangle");
+ CHECK_NULL_RETURN(clazz, NULL);
mid = env->GetMethodID(clazz, "<init>", "(IIII)V");
if (mid != 0) {
RECT rRW = {0, 0, 0, 0};
diff --git a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp
index bdcf947..9b10c7d 100644
--- a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp
@@ -328,16 +328,13 @@
jintArray bitsArray;
clazz1 = env->FindClass("java/awt/color/ColorSpace");
+ CHECK_NULL_RETURN(clazz1, NULL);
mid = env->GetStaticMethodID(clazz1, "getInstance",
"(I)Ljava/awt/color/ColorSpace;");
- if (mid == 0) {
- return NULL;
- }
+ CHECK_NULL_RETURN(mid, NULL);
cspace = env->CallStaticObjectMethod(clazz1, mid,
java_awt_color_ColorSpace_CS_GRAY);
- if (cspace == 0) {
- return NULL;
- }
+ CHECK_NULL_RETURN(cspace, NULL);
bits[0] = 8;
bitsArray = env->NewIntArray(1);
@@ -348,13 +345,10 @@
}
clazz = env->FindClass("java/awt/image/ComponentColorModel");
-
+ CHECK_NULL_RETURN(clazz, NULL);
mid = env->GetMethodID(clazz,"<init>",
"(Ljava/awt/color/ColorSpace;[IZZII)V");
-
- if (mid == 0) {
- return NULL;
- }
+ CHECK_NULL_RETURN(mid, NULL);
awt_colormodel = env->NewObject(clazz, mid,
cspace,
@@ -370,12 +364,11 @@
jbyte vbits[256/8];
jobject validBits = NULL;
+ CHECK_NULL_RETURN(hRGB, NULL);
/* Create the LUT from the color map */
try {
rgb = (unsigned int *) env->GetPrimitiveArrayCritical(hRGB, 0);
- if (rgb == NULL) {
- return NULL;
- }
+ CHECK_NULL_RETURN(rgb, NULL);
rgbP = rgb;
if (!palette) {
palette = new AwtPalette(this);
@@ -439,10 +432,12 @@
// Construct a new color model
if (!allvalid) {
jbyteArray bArray = env->NewByteArray(sizeof(vbits));
+ CHECK_NULL_RETURN(bArray, NULL);
env->SetByteArrayRegion(bArray, 0, sizeof(vbits), vbits);
validBits = JNU_NewObjectByName(env,
"java/math/BigInteger",
"([B)V", bArray);
+ JNU_CHECK_EXCEPTION_RETURN(env, NULL);
}
awt_colormodel =
JNU_NewObjectByName(env,
@@ -500,19 +495,22 @@
jintArray cacheArray = (jintArray)env->GetObjectField(colorModel,
AwtWin32GraphicsDevice::indexCMcacheID);
if (!rgbArray || !cacheArray) {
- JNU_ThrowInternalError(env,
- "rgb or lookupcache array of IndexColorModel null");
+ JNU_ThrowInternalError(env, "rgb or lookupcache array of IndexColorModel null");
return;
}
int rgbLength = env->GetArrayLength(rgbArray);
int cacheLength = env->GetArrayLength(cacheArray);
- jint *cmEntries = (jint *)env->GetPrimitiveArrayCritical(rgbArray,
- &isCopy);
- jint *cache = (jint *)env->GetPrimitiveArrayCritical(cacheArray,
- &isCopy);
- if (!cmEntries || !cache) {
- JNU_ThrowInternalError(env,
- "Problem retrieving rgb or cache critical array");
+ jint *cmEntries = (jint *)env->GetPrimitiveArrayCritical(rgbArray, &isCopy);
+ if (!cmEntries) {
+ env->ExceptionClear();
+ JNU_ThrowInternalError(env, "Problem retrieving rgb critical array");
+ return;
+ }
+ jint *cache = (jint *)env->GetPrimitiveArrayCritical(cacheArray, &isCopy);
+ if (!cache) {
+ env->ExceptionClear();
+ env->ReleasePrimitiveArrayCritical(rgbArray, cmEntries, JNI_ABORT);
+ JNU_ThrowInternalError(env, "Problem retrieving cache critical array");
return;
}
// Set the new rgb values
@@ -839,31 +837,36 @@
/* class ids */
AwtWin32GraphicsDevice::indexCMClass =
(jclass)env->NewGlobalRef(env->FindClass("java/awt/image/IndexColorModel"));
+ DASSERT(AwtWin32GraphicsDevice::indexCMClass);
+ CHECK_NULL(AwtWin32GraphicsDevice::indexCMClass);
+
AwtWin32GraphicsDevice::wToolkitClass =
(jclass)env->NewGlobalRef(env->FindClass("sun/awt/windows/WToolkit"));
-
- DASSERT(AwtWin32GraphicsDevice::indexCMClass);
DASSERT(AwtWin32GraphicsDevice::wToolkitClass);
+ CHECK_NULL(AwtWin32GraphicsDevice::wToolkitClass);
/* field ids */
AwtWin32GraphicsDevice::dynamicColorModelID = env->GetFieldID(cls,
"dynamicColorModel", "Ljava/awt/image/ColorModel;");
+ DASSERT(AwtWin32GraphicsDevice::dynamicColorModelID);
+ CHECK_NULL(AwtWin32GraphicsDevice::dynamicColorModelID);
+
AwtWin32GraphicsDevice::indexCMrgbID =
env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass, "rgb", "[I");
+ DASSERT(AwtWin32GraphicsDevice::indexCMrgbID);
+ CHECK_NULL(AwtWin32GraphicsDevice::indexCMrgbID);
+
AwtWin32GraphicsDevice::indexCMcacheID =
env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass,
"lookupcache", "[I");
+ DASSERT(AwtWin32GraphicsDevice::indexCMcacheID);
+ CHECK_NULL(AwtWin32GraphicsDevice::indexCMcacheID);
/* method ids */
AwtWin32GraphicsDevice::paletteChangedMID = env->GetStaticMethodID(
AwtWin32GraphicsDevice::wToolkitClass, "paletteChanged", "()V");
-
-
- DASSERT(AwtWin32GraphicsDevice::dynamicColorModelID);
- DASSERT(AwtWin32GraphicsDevice::indexCMrgbID);
- DASSERT(AwtWin32GraphicsDevice::indexCMcacheID);
-
DASSERT(AwtWin32GraphicsDevice::paletteChangedMID);
+ CHECK_NULL(AwtWin32GraphicsDevice::paletteChangedMID);
// Only want to call this once per session
make_uns_ordered_dither_array(img_oda_alpha, 256);
@@ -1069,16 +1072,15 @@
jclass displayModeClass = env->FindClass("java/awt/DisplayMode");
if (JNU_IsNull(env, displayModeClass)) {
- JNU_ThrowInternalError(env,
- "Could not get display mode class");
+ env->ExceptionClear();
+ JNU_ThrowInternalError(env, "Could not get display mode class");
return NULL;
}
- jmethodID cid = env->GetMethodID(displayModeClass, "<init>",
- "(IIII)V");
+ jmethodID cid = env->GetMethodID(displayModeClass, "<init>", "(IIII)V");
if (cid == NULL) {
- JNU_ThrowInternalError(env,
- "Could not get display mode constructor");
+ env->ExceptionClear();
+ JNU_ThrowInternalError(env, "Could not get display mode constructor");
return NULL;
}
@@ -1224,6 +1226,7 @@
jmethodID mid = env->GetMethodID(arrayListClass, "add",
"(Ljava/lang/Object;)Z");
if (mid == NULL) {
+ env->ExceptionClear();
JNU_ThrowInternalError(env,
"Could not get method java.util.ArrayList.add()");
return;
@@ -1264,6 +1267,7 @@
if (dm.dmBitsPerPel >= 8) {
addDisplayMode(env, arrayList, dm.dmPelsWidth, dm.dmPelsHeight,
dm.dmBitsPerPel, dm.dmDisplayFrequency);
+ JNU_CHECK_EXCEPTION(env);
}
}
diff --git a/jdk/src/windows/native/sun/windows/awt_Window.cpp b/jdk/src/windows/native/sun/windows/awt_Window.cpp
index e3a7289..1242bba 100644
--- a/jdk/src/windows/native/sun/windows/awt_Window.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp
@@ -483,6 +483,8 @@
env->DeleteLocalRef(target);
InitType(env, peer);
+ JNU_CHECK_EXCEPTION(env);
+
TweakStyle(windowStyle, windowExStyle);
AwtCanvas::CreateHWnd(env, title,
@@ -684,15 +686,27 @@
if (point2DClassID == NULL) {
jclass point2DClassIDLocal = env->FindClass("java/awt/geom/Point2D");
+ if (point2DClassIDLocal == NULL) {
+ env->DeleteLocalRef(point2D);
+ return;
+ }
point2DClassID = (jclass)env->NewGlobalRef(point2DClassIDLocal);
env->DeleteLocalRef(point2DClassIDLocal);
}
if (point2DGetXMID == NULL) {
point2DGetXMID = env->GetMethodID(point2DClassID, "getX", "()D");
+ if (point2DGetXMID == NULL) {
+ env->DeleteLocalRef(point2D);
+ return;
+ }
}
if (point2DGetYMID == NULL) {
point2DGetYMID = env->GetMethodID(point2DClassID, "getY", "()D");
+ if (point2DGetYMID == NULL) {
+ env->DeleteLocalRef(point2D);
+ return;
+ }
}
@@ -1071,6 +1085,7 @@
if (JNU_IsInstanceOfByName(env, target, "javax/swing/Popup$HeavyWeightWindow") > 0) {
window->m_isRetainingHierarchyZOrder = TRUE;
}
+ if (env->ExceptionCheck()) goto done;
DWORD style = WS_CLIPCHILDREN | WS_POPUP;
DWORD exStyle = WS_EX_NOACTIVATE;
if (GetRTL()) {
@@ -1378,6 +1393,10 @@
((AwtFrame*)this)->GetMenuBar()) {
m_insets.top += ::GetSystemMetrics(SM_CYMENU);
}
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(target);
+ return FALSE;
+ }
m_insets.bottom += extraBottomInsets;
env->DeleteLocalRef(target);
}
@@ -1445,14 +1464,13 @@
classEvent = (jclass)env->NewGlobalRef(classEvent);
}
env->PopLocalFrame(0);
+ CHECK_NULL(classEvent);
}
static jmethodID eventInitMID = NULL;
if (eventInitMID == NULL) {
eventInitMID = env->GetMethodID(classEvent, "<init>",
"(Ljava/awt/Component;I)V");
- if (eventInitMID == NULL) {
- return;
- }
+ CHECK_NULL(eventInitMID);
}
if (env->EnsureLocalCapacity(2) < 0) {
return;
@@ -1462,6 +1480,10 @@
target, eventId);
DASSERT(!safe_ExceptionOccurred(env));
DASSERT(event != NULL);
+ if (event == NULL) {
+ env->DeleteLocalRef(target);
+ return;
+ }
SendEvent(event);
env->DeleteLocalRef(target);
@@ -1503,10 +1525,7 @@
jclass sequencedEventClsLocal
= env->FindClass("java/awt/SequencedEvent");
DASSERT(sequencedEventClsLocal);
- if (sequencedEventClsLocal == NULL) {
- /* exception already thrown */
- return;
- }
+ CHECK_NULL(sequencedEventClsLocal);
sequencedEventCls =
(jclass)env->NewGlobalRef(sequencedEventClsLocal);
env->DeleteLocalRef(sequencedEventClsLocal);
@@ -1517,6 +1536,7 @@
sequencedEventConst =
env->GetMethodID(sequencedEventCls, "<init>",
"(Ljava/awt/AWTEvent;)V");
+ CHECK_NULL(sequencedEventConst);
}
if (env->EnsureLocalCapacity(3) < 0) {
@@ -1539,6 +1559,7 @@
env->DeleteLocalRef(jOpposite); jOpposite = NULL;
}
env->DeleteLocalRef(target); target = NULL;
+ CHECK_NULL(event);
if (id == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS ||
id == java_awt_event_WindowEvent_WINDOW_LOST_FOCUS)
@@ -2024,10 +2045,15 @@
jclass peerCls = env->GetObjectClass(m_peerObject);
DASSERT(peerCls);
+ CHECK_NULL(peerCls);
jmethodID draggedID = env->GetMethodID(peerCls, "draggedToNewScreen",
"()V");
DASSERT(draggedID);
+ if (draggedID == NULL) {
+ env->DeleteLocalRef(peerCls);
+ return;
+ }
env->CallVoidMethod(m_peerObject, draggedID);
m_screenNum = curScrn;
@@ -2505,6 +2531,7 @@
}
m_hIconSm = NULL;
m_hIcon = CreateIconFromRaster(env, iconRaster, w, h);
+ JNU_CHECK_EXCEPTION(env);
m_hIconSm = CreateIconFromRaster(env, smallIconRaster, smw, smh);
m_iconInherited = (m_hIcon == NULL);
@@ -3057,22 +3084,23 @@
{
TRY;
- AwtWindow::warningStringID =
- env->GetFieldID(cls, "warningString", "Ljava/lang/String;");
- AwtWindow::locationByPlatformID =
- env->GetFieldID(cls, "locationByPlatform", "Z");
- AwtWindow::securityWarningWidthID =
- env->GetFieldID(cls, "securityWarningWidth", "I");
- AwtWindow::securityWarningHeightID =
- env->GetFieldID(cls, "securityWarningHeight", "I");
- AwtWindow::getWarningStringMID =
- env->GetMethodID(cls, "getWarningString", "()Ljava/lang/String;");
- AwtWindow::autoRequestFocusID =
- env->GetFieldID(cls, "autoRequestFocus", "Z");
- AwtWindow::calculateSecurityWarningPositionMID =
- env->GetMethodID(cls, "calculateSecurityWarningPosition", "(DDDD)Ljava/awt/geom/Point2D;");
+ CHECK_NULL(AwtWindow::warningStringID =
+ env->GetFieldID(cls, "warningString", "Ljava/lang/String;"));
+ CHECK_NULL(AwtWindow::locationByPlatformID =
+ env->GetFieldID(cls, "locationByPlatform", "Z"));
+ CHECK_NULL(AwtWindow::securityWarningWidthID =
+ env->GetFieldID(cls, "securityWarningWidth", "I"));
+ CHECK_NULL(AwtWindow::securityWarningHeightID =
+ env->GetFieldID(cls, "securityWarningHeight", "I"));
+ CHECK_NULL(AwtWindow::getWarningStringMID =
+ env->GetMethodID(cls, "getWarningString", "()Ljava/lang/String;"));
+ CHECK_NULL(AwtWindow::autoRequestFocusID =
+ env->GetFieldID(cls, "autoRequestFocus", "Z"));
+ CHECK_NULL(AwtWindow::calculateSecurityWarningPositionMID =
+ env->GetMethodID(cls, "calculateSecurityWarningPosition", "(DDDD)Ljava/awt/geom/Point2D;"));
jclass windowTypeClass = env->FindClass("java/awt/Window$Type");
+ CHECK_NULL(windowTypeClass);
AwtWindow::windowTypeNameMID =
env->GetMethodID(windowTypeClass, "name", "()Ljava/lang/String;");
env->DeleteLocalRef(windowTypeClass);
@@ -3099,10 +3127,10 @@
{
TRY;
- AwtWindow::sysXID = env->GetFieldID(cls, "sysX", "I");
- AwtWindow::sysYID = env->GetFieldID(cls, "sysY", "I");
- AwtWindow::sysWID = env->GetFieldID(cls, "sysW", "I");
- AwtWindow::sysHID = env->GetFieldID(cls, "sysH", "I");
+ CHECK_NULL(AwtWindow::sysXID = env->GetFieldID(cls, "sysX", "I"));
+ CHECK_NULL(AwtWindow::sysYID = env->GetFieldID(cls, "sysY", "I"));
+ CHECK_NULL(AwtWindow::sysWID = env->GetFieldID(cls, "sysW", "I"));
+ CHECK_NULL(AwtWindow::sysHID = env->GetFieldID(cls, "sysH", "I"));
AwtWindow::windowTypeID = env->GetFieldID(cls, "windowType",
"Ljava/awt/Window$Type;");
diff --git a/jdk/src/windows/native/sun/windows/awt_new.cpp b/jdk/src/windows/native/sun/windows/awt_new.cpp
index e22aa3b..306f08d 100644
--- a/jdk/src/windows/native/sun/windows/awt_new.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_new.cpp
@@ -163,18 +163,13 @@
safe_ExceptionOccurred(JNIEnv *env) throw (std::bad_alloc) {
jthrowable xcp = env->ExceptionOccurred();
if (xcp != NULL) {
- env->ExceptionClear(); // if we don't do this, FindClass will fail
-
- jclass outofmem = env->FindClass("java/lang/OutOfMemoryError");
- DASSERT(outofmem != NULL);
- jboolean isOutofmem = env->IsInstanceOf(xcp, outofmem);
-
- env->DeleteLocalRef(outofmem);
-
- if (isOutofmem) {
+ env->ExceptionClear(); // if we don't do this, isInstanceOf will fail
+ jint isOutofmem = JNU_IsInstanceOfByName(env, xcp, "java/lang/OutOfMemoryError");
+ if (isOutofmem > 0) {
env->DeleteLocalRef(xcp);
throw std::bad_alloc();
} else {
+ env->ExceptionClear();
// rethrow exception
env->Throw(xcp);
return xcp;
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index 96d6a4c..966f6c8 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -234,15 +234,6 @@
java/security/KeyPairGenerator/SolarisShortDSA.java solaris-all
sun/security/tools/keytool/standard.sh solaris-all
-# 8000439: NPG: REGRESSION : sun/security/krb5/auto/MaxRetries.java fails with timeout
-sun/security/krb5/auto/MaxRetries.java solaris-sparcv9
-
-# 8006690: sun/security/krb5/auto/BadKdc1.java fails intermittently
-sun/security/krb5/auto/BadKdc1.java solaris-sparcv9
-sun/security/krb5/auto/BadKdc2.java solaris-sparcv9
-sun/security/krb5/auto/BadKdc3.java solaris-sparcv9
-sun/security/krb5/auto/BadKdc4.java solaris-sparcv9
-
############################################################################
# jdk_sound
diff --git a/jdk/test/com/sun/nio/sctp/SctpChannel/ReceiveIntoDirect.java b/jdk/test/com/sun/nio/sctp/SctpChannel/ReceiveIntoDirect.java
new file mode 100644
index 0000000..e7b23d0
--- /dev/null
+++ b/jdk/test/com/sun/nio/sctp/SctpChannel/ReceiveIntoDirect.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2014, 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 8034181
+ * @summary SIGBUS in SctpChannelImpl receive
+ * @author chegar
+ */
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import com.sun.nio.sctp.AbstractNotificationHandler;
+import com.sun.nio.sctp.AssociationChangeNotification;
+import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;
+import com.sun.nio.sctp.HandlerResult;
+import com.sun.nio.sctp.MessageInfo;
+import com.sun.nio.sctp.Notification;
+import com.sun.nio.sctp.PeerAddressChangeNotification;
+import com.sun.nio.sctp.SctpChannel;
+import com.sun.nio.sctp.SctpServerChannel;
+import com.sun.nio.sctp.ShutdownNotification;
+import static java.lang.System.out;
+import static java.lang.System.err;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+
+public class ReceiveIntoDirect {
+ /* suitably small message to NOT overrun small buffers */
+ final byte[] msgBytes = "Hello".getBytes(US_ASCII);
+
+ /* number of client connections/combinations (accepted by the server) */
+ final int NUM_CONNECTIONS = 75;
+
+ void test(String[] args) throws IOException {
+ SocketAddress address = null;
+ Server server;
+
+ if (!Util.isSCTPSupported()) {
+ out.println("SCTP protocol is not supported");
+ out.println("Test cannot be run");
+ return;
+ }
+
+ if (args.length == 2) {
+ /* requested to connecct to a specific address */
+ try {
+ int port = Integer.valueOf(args[1]);
+ address = new InetSocketAddress(args[0], port);
+ } catch (NumberFormatException nfe) {
+ err.println(nfe);
+ }
+ } else {
+ /* start server on local machine, default */
+ server = new Server();
+ server.start();
+ address = server.address();
+ debug("Server started and listening on " + address);
+ }
+
+ /* many combinations with varing buffer sizes, and offsets */
+ runWithManyOffsets(address, 20);
+ runWithManyOffsets(address, 49);
+ runWithManyOffsets(address, 50);
+ runWithManyOffsets(address, 51);
+ runWithManyOffsets(address, 1024);
+ }
+
+ void runWithManyOffsets(SocketAddress addr, int bufferSize)
+ throws IOException
+ {
+ doTest(addr, bufferSize, 1);
+ doTest(addr, bufferSize, 2);
+ doTest(addr, bufferSize, 3);
+ doTest(addr, bufferSize, 4);
+ doTest(addr, bufferSize, 5);
+ doTest(addr, bufferSize, 6);
+ doTest(addr, bufferSize, 7);
+ doTest(addr, bufferSize, 8);
+ doTest(addr, bufferSize, 9);
+ doTest(addr, bufferSize, 10);
+ doTest(addr, bufferSize, 11);
+ doTest(addr, bufferSize, 12);
+ doTest(addr, bufferSize, 13);
+ doTest(addr, bufferSize, 14);
+ doTest(addr, bufferSize, 15);
+ }
+
+ void doTest(SocketAddress peerAddress, int bufferSize, int bufferOffset)
+ throws IOException
+ {
+ debug("\n\nTesting with bufferSize " + bufferSize + " and offset " + bufferOffset);
+ assert bufferOffset + msgBytes.length <= bufferSize :
+ "buffer offset + message length greater than buffer size ";
+
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize);
+ MessageInfo info;
+
+ try (SctpChannel channel = SctpChannel.open()) {
+ channel.connect(peerAddress);
+
+ ReceiveNotificationHandler handler =
+ new ReceiveNotificationHandler();
+
+ /* TEST 1: Assoc/peer change notif into direct buffer with offest */
+ do {
+ debug("Test 1: Assoc/peer change with offset " + bufferOffset);
+ buffer.position(bufferOffset);
+ info = channel.receive(buffer, null, handler);
+ if (info == null) {
+ fail("unexpected null from receive");
+ return;
+ }
+ } while (!info.isComplete());
+
+ buffer.flip().position(bufferOffset);
+ check(handler.receivedCommUp(), "SCTP_COMM_UP not received");
+ check(info != null, "info is null");
+ check(info.address() != null, "address is null");
+ check(info.association() != null, "association is null");
+ check(info.isComplete(), "message is not complete");
+ check(info.isUnordered() != true,
+ "message should not be unordered");
+ check(info.streamNumber() >= 0, "invalid stream number");
+ check(info.bytes() == msgBytes.length,
+ "bytes received not equal to message length");
+ check(info.bytes() == buffer.remaining(), "bytes != remaining");
+ check(Util.compare(buffer, msgBytes),
+ "received message not the same as sent message");
+
+ /* TEST 2: shutdown notification with offset */
+ debug("Test 2: shutdown notif with offset " + bufferOffset);
+ buffer.clear().position(bufferOffset);
+ while ((info = channel.receive(buffer, null, handler )) != null &&
+ info.bytes() != -1 );
+ }
+ }
+
+ class Server implements Runnable
+ {
+ private final InetSocketAddress serverAddr;
+ private final SctpServerChannel ssc;
+
+ public Server() throws IOException {
+ ssc = SctpServerChannel.open().bind(null);
+ java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
+ if (addrs.isEmpty())
+ debug("addrs should not be empty");
+
+ serverAddr = (InetSocketAddress) addrs.iterator().next();
+ }
+
+ public void start() {
+ (new Thread(this, "Server-" + serverAddr.getPort())).start();
+ }
+
+ public InetSocketAddress address() {
+ return serverAddr;
+ }
+
+ @Override
+ public void run() {
+ try {
+ for (int i=0; i<NUM_CONNECTIONS; i++) {
+ SctpChannel sc = ssc.accept();
+
+ /* send a small message */
+ MessageInfo info = MessageInfo.createOutgoing(null, 0);
+ ByteBuffer buf = ByteBuffer.allocateDirect(Util.SMALL_BUFFER);
+ buf.put(msgBytes);
+ buf.flip();
+
+ debug("sending small message: " + buf);
+ sc.send(buf, info);
+
+ sc.shutdown();
+ sc.close();
+ }
+ } catch (IOException x) {
+ unexpected(x);
+ } finally {
+ try { ssc.close(); }
+ catch (IOException x) { unexpected(x); }
+ }
+ }
+ }
+
+ class ReceiveNotificationHandler extends AbstractNotificationHandler<Object>
+ {
+ boolean receivedCommUp; // false
+
+ public ReceiveNotificationHandler() { }
+
+ public boolean receivedCommUp() {
+ return receivedCommUp;
+ }
+
+ @Override
+ public HandlerResult handleNotification(
+ Notification notification, Object attachment) {
+ fail("Unknown notification type");
+ return HandlerResult.CONTINUE;
+ }
+
+ @Override
+ public HandlerResult handleNotification(
+ AssociationChangeNotification notification, Object attachment) {
+ AssocChangeEvent event = notification.event();
+ debug("AssociationChangeNotification");
+ debug(" Association: " + notification.association());
+ debug(" Event: " + event);
+
+ if (event.equals(AssocChangeEvent.COMM_UP))
+ receivedCommUp = true;
+
+ return HandlerResult.CONTINUE;
+ }
+
+ @Override
+ public HandlerResult handleNotification(
+ PeerAddressChangeNotification pacn, Object unused)
+ {
+ debug("PeerAddressChangeNotification: " + pacn);
+ return HandlerResult.CONTINUE;
+ }
+
+ @Override
+ public HandlerResult handleNotification(
+ ShutdownNotification notification, Object attachment) {
+ debug("ShutdownNotification");
+ debug(" Association: " + notification.association());
+ return HandlerResult.CONTINUE;
+ }
+ }
+ //--------------------- Infrastructure ---------------------------
+ boolean debug = true;
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
+ void debug(String message) {if(debug) {
+ System.out.println(Thread.currentThread() + " " + message); } }
+ public static void main(String[] args) throws Throwable {
+ Class<?> k = new Object(){}.getClass().getEnclosingClass();
+ try {k.getMethod("instanceMain",String[].class)
+ .invoke( k.newInstance(), (Object) args);}
+ catch (Throwable e) {throw e.getCause();}}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+
+}
diff --git a/jdk/test/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java b/jdk/test/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java
index 7348f66..79b5a3a 100644
--- a/jdk/test/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java
+++ b/jdk/test/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, 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
@@ -23,7 +23,7 @@
/*
test
- @bug 6998877
+ @bug 6998877 8022531
@summary After double-click on the folder names, FileNameOverrideTest FAILED
@author Sergey.Bylokhov@oracle.com area=awt.filedialog
@library ../../regtesthelpers
@@ -59,7 +59,8 @@
String[] instructions = {
"1) Click on 'Show File Dialog' button. A file dialog will come up.",
- "2) Double-click on '" + clickDirName + "' and click OK.",
+ "2) Double-click on '" + clickDirName + "' and click a confirmation",
+ " button, it can be 'OK', 'Save' or any other platform-dependent name.",
"3) See result of the test below"
};
diff --git a/jdk/test/java/awt/Frame/7024749/bug7024749.java b/jdk/test/java/awt/Frame/7024749/bug7024749.java
index 4e7f682..7035435 100644
--- a/jdk/test/java/awt/Frame/7024749/bug7024749.java
+++ b/jdk/test/java/awt/Frame/7024749/bug7024749.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7024749
+ * @bug 7024749 8019990
* @summary JDK7 b131---a crash in: Java_sun_awt_windows_ThemeReader_isGetThemeTransitionDurationDefined+0x75
* @library ../../regtesthelpers
* @build Util
diff --git a/jdk/test/java/awt/Frame/SlideNotResizableTest/SlideNotResizableTest.java b/jdk/test/java/awt/Frame/SlideNotResizableTest/SlideNotResizableTest.java
new file mode 100644
index 0000000..37df055
--- /dev/null
+++ b/jdk/test/java/awt/Frame/SlideNotResizableTest/SlideNotResizableTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 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 sun.awt.SunToolkit;
+
+import java.awt.*;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.event.InputEvent;
+
+/**
+ * @test
+ * @bug 8032595
+ * @summary setResizable(false) makes a frame slide down
+ * @author Petr Pchelko
+ */
+
+public class SlideNotResizableTest {
+
+ private static volatile boolean passed = false;
+ private static final Dimension FRAME_SIZE = new Dimension(100, 100);
+ private static final Point FRAME_LOCATION = new Point(200, 200);
+
+ public static void main(String[] args) throws Throwable {
+ Frame aFrame = null;
+ try {
+ aFrame = new Frame();
+ aFrame.setSize(FRAME_SIZE);
+ aFrame.setLocation(FRAME_LOCATION);
+ aFrame.setResizable(false);
+ aFrame.setVisible(true);
+
+ sync();
+
+ if (!aFrame.getLocation().equals(FRAME_LOCATION)) {
+ throw new RuntimeException("FAILED: Wrong frame position");
+ }
+ } finally {
+ if (aFrame != null) {
+ aFrame.dispose();
+ }
+ }
+ }
+
+ private static void sync() throws InterruptedException {
+ ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
+ Thread.sleep(1000);
+ }
+}
diff --git a/jdk/test/java/awt/Paint/bug8024864.java b/jdk/test/java/awt/Paint/bug8024864.java
index caa6290..42580a4 100644
--- a/jdk/test/java/awt/Paint/bug8024864.java
+++ b/jdk/test/java/awt/Paint/bug8024864.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 8024864
+ * @bug 8024864 8031422
* @summary [macosx] Problems with rendering of controls
* @author Petr Pchelko
* @library ../regtesthelpers
@@ -65,7 +65,7 @@
Util.waitForIdle(r);
Dimension frameSize = frame.getSize();
- Point loc = new Point(frameSize.width - 5, frameSize.height - 5);
+ Point loc = new Point(frameSize.width - 15, frameSize.height - 15);
SwingUtilities.convertPointToScreen(loc, frame);
Color c = r.getPixelColor(loc.x, loc.y);
diff --git a/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
index 977f1b4..8b40460 100644
--- a/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
+++ b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
@@ -1,7 +1,7 @@
#!/bin/ksh -p
#
-# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2014, 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
@@ -25,7 +25,7 @@
#
# @test
-# @bug 6282388
+# @bug 6282388 8030640
# @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit
# @author artem.ananiev@sun.com: area=awt.headless
# @compile TestWrapped.java
@@ -59,30 +59,14 @@
# Checking for proper OS
OS=`uname -s`
case "$OS" in
- SunOS )
- VAR="One value for Sun"
- DEFAULT_JDK=/usr/local/java/jdk1.2/solaris
+ SunOS | Linux | Darwin | CYGWIN* )
FILESEP="/"
;;
-
- Linux )
- VAR="A different value for Linux"
- DEFAULT_JDK=/usr/local/java/jdk1.4/linux-i386
- FILESEP="/"
- ;;
-
- Windows* | CYGWIN* )
- VAR="A different value for Win32"
- DEFAULT_JDK=/usr/local/java/jdk1.2/win32
+
+ Windows* )
FILESEP="\\"
;;
- Darwin)
- VAR="Lets not forget about Mac"
- DEFAULT_JDK=$(/usr/libexec/java_home)
- FILESEP="/"
- ;;
-
# catch all other OSs
* )
echo "Unrecognized system! $OS"
@@ -113,8 +97,7 @@
# THIS IS THE JDK BEING TESTED.
if [ -n "$1" ] ;
then TESTJAVA=$1
- else echo "no JDK specified on command line so using default!"
- TESTJAVA=$DEFAULT_JDK
+ else fail "no JDK specified on command line!"
fi
TESTSRC=.
TESTCLASSES=.
diff --git a/jdk/test/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java b/jdk/test/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java
index c10094e..310e78f 100644
--- a/jdk/test/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java
+++ b/jdk/test/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -23,7 +23,7 @@
/*
@test
- @bug 7154072
+ @bug 7154072 7161320
@summary Tests that key events with modifiers are not swallowed.
@author anton.tarasov: area=awt.focus
@library ../../../regtesthelpers
@@ -49,6 +49,11 @@
static Robot r;
public static void main(String[] args) {
+ if (sun.awt.OSInfo.getOSType() == sun.awt.OSInfo.OSType.WINDOWS) {
+ System.out.println("Skipped. Test not for MS Windows.");
+ return;
+ }
+
f.add(t);
f.pack();
f.setVisible(true);
diff --git a/jdk/test/java/awt/image/MultiResolutionImage/NSImageToMultiResolutionImageTest.java b/jdk/test/java/awt/image/MultiResolutionImage/NSImageToMultiResolutionImageTest.java
new file mode 100644
index 0000000..af80924
--- /dev/null
+++ b/jdk/test/java/awt/image/MultiResolutionImage/NSImageToMultiResolutionImageTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 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.awt.Image;
+import java.awt.Toolkit;
+import sun.awt.OSInfo;
+import sun.awt.image.MultiResolutionImage;
+/*
+ * @test
+ * @bug 8033534 8035069
+ * @summary [macosx] Get MultiResolution image from native system
+ * @author Alexander Scherbatiy
+ * @run main NSImageToMultiResolutionImageTest
+ */
+
+public class NSImageToMultiResolutionImageTest {
+
+ public static void main(String[] args) throws Exception {
+
+ if (OSInfo.getOSType() != OSInfo.OSType.MACOSX) {
+ return;
+ }
+
+ String icon = "NSImage://NSApplicationIcon";
+ final Image image = Toolkit.getDefaultToolkit().getImage(icon);
+
+ if (!(image instanceof MultiResolutionImage)) {
+ throw new RuntimeException("Icon does not have resolution variants!");
+ }
+
+ MultiResolutionImage multiResolutionImage = (MultiResolutionImage) image;
+
+ int width = 0;
+ int height = 0;
+
+ for (Image resolutionVariant : multiResolutionImage.getResolutionVariants()) {
+ int rvWidth = resolutionVariant.getWidth(null);
+ int rvHeight = resolutionVariant.getHeight(null);
+ if (rvWidth < width || rvHeight < height) {
+ throw new RuntimeException("Resolution variants are not sorted!");
+ }
+ width = rvWidth;
+ height = rvHeight;
+ }
+ }
+}
diff --git a/jdk/test/java/awt/regtesthelpers/process/ProcessCommunicator.java b/jdk/test/java/awt/regtesthelpers/process/ProcessCommunicator.java
index 86e69e67..8c0e6db 100644
--- a/jdk/test/java/awt/regtesthelpers/process/ProcessCommunicator.java
+++ b/jdk/test/java/awt/regtesthelpers/process/ProcessCommunicator.java
@@ -81,7 +81,7 @@
public static ProcessResults executeChildProcess(final Class classToExecute,
final String [] args)
{
- return executeChildProcess(classToExecute, " ", args);
+ return executeChildProcess(classToExecute, System.getProperty("java.class.path"), args);
}
/**
diff --git a/jdk/test/java/lang/ProcessBuilder/CloseRace.java b/jdk/test/java/lang/ProcessBuilder/CloseRace.java
new file mode 100644
index 0000000..a9afbd2
--- /dev/null
+++ b/jdk/test/java/lang/ProcessBuilder/CloseRace.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2013, 2014 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 8024521
+ * @summary Closing ProcessPipeInputStream at the time the process exits is racy
+ * and leads to data corruption. Run this test manually (as
+ * an ordinary java program) with -Xmx8M to repro bug 8024521.
+ * @run main/othervm -Xmx8M -Dtest.duration=2 CloseRace
+ */
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+
+public class CloseRace {
+ private static final String BIG_FILE = "bigfile";
+
+ private static final int[] procFDs = new int[6];
+
+ /** default value sufficient to repro bug 8024521. */
+ private static final int testDurationSeconds
+ = Integer.getInteger("test.duration", 600);
+
+ private static final CountDownLatch threadsStarted
+ = new CountDownLatch(2);
+
+ static boolean fdInUse(int i) {
+ return new File("/proc/self/fd/" + i).exists();
+ }
+
+ static boolean[] procFDsInUse() {
+ boolean[] inUse = new boolean[procFDs.length];
+ for (int i = 0; i < procFDs.length; i++)
+ inUse[i] = fdInUse(procFDs[i]);
+ return inUse;
+ }
+
+ static int count(boolean[] bits) {
+ int count = 0;
+ for (int i = 0; i < bits.length; i++)
+ count += bits[i] ? 1 : 0;
+ return count;
+ }
+
+ static void dumpAllStacks() {
+ System.err.println("Start of dump");
+ final Map<Thread, StackTraceElement[]> allStackTraces
+ = Thread.getAllStackTraces();
+ for (Thread thread : allStackTraces.keySet()) {
+ System.err.println("Thread " + thread.getName());
+ for (StackTraceElement element : allStackTraces.get(thread))
+ System.err.println("\t" + element);
+ }
+ System.err.println("End of dump");
+ }
+
+ public static void main(String args[]) throws Exception {
+ if (!(new File("/proc/self/fd").isDirectory()))
+ return;
+
+ // Catch Errors from process reaper
+ Thread.setDefaultUncaughtExceptionHandler
+ ((t, e) -> { e.printStackTrace(); System.exit(1); });
+
+ try (RandomAccessFile f = new RandomAccessFile(BIG_FILE, "rw")) {
+ f.setLength(Runtime.getRuntime().maxMemory()); // provoke OOME
+ }
+
+ for (int i = 0, j = 0; j < procFDs.length; i++)
+ if (!fdInUse(i))
+ procFDs[j++] = i;
+
+ Thread[] threads = {
+ new Thread(new OpenLoop()),
+ new Thread(new ExecLoop()),
+ };
+ for (Thread thread : threads)
+ thread.start();
+
+ threadsStarted.await();
+ Thread.sleep(testDurationSeconds * 1000);
+
+ for (Thread thread : threads)
+ thread.interrupt();
+ for (Thread thread : threads) {
+ thread.join(10_000);
+ if (thread.isAlive()) {
+ dumpAllStacks();
+ throw new Error("At least one child thread ("
+ + thread.getName()
+ + ") failed to finish gracefully");
+ }
+ }
+ }
+
+ static class OpenLoop implements Runnable {
+ public void run() {
+ threadsStarted.countDown();
+ while (!Thread.interrupted()) {
+ try {
+ // wait for ExecLoop to finish creating process
+ do {
+ if (Thread.interrupted())
+ return;
+ } while (count(procFDsInUse()) != 3);
+ List<InputStream> iss = new ArrayList<>(4);
+
+ // eat up three "holes" (closed ends of pipe fd pairs)
+ for (int i = 0; i < 3; i++)
+ iss.add(new FileInputStream(BIG_FILE));
+ do {
+ if (Thread.interrupted())
+ return;
+ } while (count(procFDsInUse()) == procFDs.length);
+ // hopefully this will racily occupy empty fd slot
+ iss.add(new FileInputStream(BIG_FILE));
+ Thread.sleep(1); // Widen race window
+ for (InputStream is : iss)
+ is.close();
+ } catch (InterruptedException e) {
+ break;
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+ }
+ }
+
+ static class ExecLoop implements Runnable {
+ public void run() {
+ threadsStarted.countDown();
+ ProcessBuilder builder = new ProcessBuilder("/bin/true");
+ while (!Thread.interrupted()) {
+ try {
+ // wait for OpenLoop to finish
+ do {
+ if (Thread.interrupted())
+ return;
+ } while (count(procFDsInUse()) > 0);
+ Process process = builder.start();
+ InputStream is = process.getInputStream();
+ process.waitFor();
+ is.close();
+ } catch (InterruptedException e) {
+ break;
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+ }
+ }
+}
diff --git a/jdk/test/java/lang/Runtime/exec/CloseRace.java b/jdk/test/java/lang/Runtime/exec/CloseRace.java
deleted file mode 100644
index a1e5790..0000000
--- a/jdk/test/java/lang/Runtime/exec/CloseRace.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2013, 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 8024521
- * @summary Closing ProcessPipeInputStream at the time the process exits is racy
- * and leads to the data corruption.
- * @library /lib/testlibrary
- * @run main/othervm/timeout=80 CloseRace
- */
-
-/**
- * This test has a little chance to catch the race during the given default
- * time gap of 20 seconds. To increase the time gap, set the system property
- * CloseRaceTimeGap=N to the number of seconds.
- * Jtreg's timeoutFactor should also be set appropriately.
- *
- * For example, to run the test for 10 minutes:
- * > jtreg \
- * -testjdk:$(PATH_TO_TESTED_JDK) \
- * -timeoutFactor:10 \
- * -DCloseRaceTimeGap=600 \
- * $(PATH_TO_TESTED_JDK_SOURCE)/test/java/lang/Runtime/exec/CloseRace.java
- */
-
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import jdk.testlibrary.OutputAnalyzer;
-import static jdk.testlibrary.ProcessTools.*;
-
-public class CloseRace {
-
- public static void main(String args[]) throws Exception {
- ProcessBuilder pb = createJavaProcessBuilder("-Xmx64M", "CloseRace$Child",
- System.getProperty("CloseRaceTimeGap", "20"));
- OutputAnalyzer oa = new OutputAnalyzer(pb.start());
- oa.stderrShouldNotContain("java.lang.OutOfMemoryError");
- }
-
- public static class Child {
- private static final String BIG_FILE = "bigfile";
- private static final String SMALL_FILE = "smallfile";
- private static int timeGap = 20; // seconds
-
- public static void main(String args[]) throws Exception {
- if (args.length > 0) {
- try {
- timeGap = Integer.parseUnsignedInt(args[0]);
- timeGap = Integer.max(timeGap, 10);
- timeGap = Integer.min(timeGap, 10 * 60 * 60); // no more than 10 hours
- } catch (NumberFormatException ignore) {}
- }
- try (RandomAccessFile f = new RandomAccessFile(BIG_FILE, "rw")) {
- f.setLength(1024 * 1024 * 1024); // 1 Gb, greater than max heap size
- }
- try (FileOutputStream fs = new FileOutputStream(SMALL_FILE);
- PrintStream ps = new PrintStream(fs)) {
- for (int i = 0; i < 128; ++i)
- ps.println("line of text");
- }
-
- List<Thread> threads = new LinkedList<>();
- for (int i = 0; i < 99; ++i) {
- Thread t = new Thread (new OpenLoop());
- t.start();
- threads.add(t);
- }
- Thread t2 = new Thread (new ExecLoop());
- t2.start();
- threads.add(t2);
-
- Thread.sleep(timeGap);
-
- for (Thread t : threads) {
- t.interrupt();
- t.join();
- }
- }
-
- private static class OpenLoop implements Runnable {
- public void run() {
- final Path bigFilePath = Paths.get(BIG_FILE);
- while (!Thread.interrupted()) {
- try (InputStream in = Files.newInputStream(bigFilePath)) {
- // Widen the race window by sleeping 1ms
- Thread.sleep(1);
- } catch (InterruptedException e) {
- break;
- } catch (Exception e) {
- System.err.println(e);
- }
- }
- }
- }
-
- private static class ExecLoop implements Runnable {
- public void run() {
- List<String> command = new ArrayList<>(
- Arrays.asList("/bin/cat", SMALL_FILE));
- while (!Thread.interrupted()) {
- try {
- ProcessBuilder builder = new ProcessBuilder(command);
- final Process process = builder.start();
- InputStream is = process.getInputStream();
- InputStreamReader isr = new InputStreamReader(is);
- BufferedReader br = new BufferedReader(isr);
- while (br.readLine() != null) {}
- process.waitFor();
- isr.close();
- } catch (InterruptedException e) {
- break;
- } catch (Exception e) {
- System.err.println(e);
- }
- }
- }
- }
- }
-}
diff --git a/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java
new file mode 100644
index 0000000..739ca6d
--- /dev/null
+++ b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package test.java.lang.invoke.MethodHandles;
+
+import com.oracle.testlibrary.jsr292.Helper;
+import jdk.testlibrary.Asserts;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/* @test
+ * @library /lib/testlibrary/jsr292 /lib/testlibrary/
+ * @compile CatchExceptionTest.java
+ * @run main/othervm -esa test.java.lang.invoke.MethodHandles.CatchExceptionTest
+ */
+public class CatchExceptionTest {
+ private static final List<Class<?>> ARGS_CLASSES;
+ protected static final int MAX_ARITY = Helper.MAX_ARITY - 1;
+ static {
+ Class<?> classes[] = {
+ Object.class,
+ long.class,
+ int.class,
+ byte.class,
+ Integer[].class,
+ double[].class,
+ String.class,
+ };
+ List<Class<?>> list = new ArrayList<>(MAX_ARITY);
+ for (int i = 0; i < MAX_ARITY; ++i) {
+ list.add(classes[Helper.RNG.nextInt(classes.length)]);
+ }
+ ARGS_CLASSES = Collections.unmodifiableList(list);
+ }
+
+ private final TestCase testCase;
+ private final int nargs;
+ private final int argsCount;
+ private final MethodHandle catcher;
+ private int dropped;
+ private MethodHandle thrower;
+
+
+ public CatchExceptionTest(TestCase testCase, final boolean isVararg, final int argsCount,
+ final int catchDrops) {
+ this.testCase = testCase;
+ this.dropped = catchDrops;
+ if (Helper.IS_VERBOSE) {
+ System.out.printf("CatchException::CatchException(%s, isVararg=%b " +
+ "argsCount=%d catchDrops=%d)%n",
+ testCase, isVararg, argsCount, catchDrops
+ );
+ }
+ MethodHandle thrower = testCase.thrower;
+ int throwerLen = thrower.type().parameterCount();
+ List<Class<?>> classes;
+ int extra = Math.max(0, argsCount - throwerLen);
+ classes = getThrowerParams(isVararg, extra);
+ this.argsCount = throwerLen + classes.size();
+ thrower = Helper.addTrailingArgs(thrower, this.argsCount, classes);
+ if (isVararg && argsCount > throwerLen) {
+ MethodType mt = thrower.type();
+ Class<?> lastParam = mt.parameterType(mt.parameterCount() - 1);
+ thrower = thrower.asVarargsCollector(lastParam);
+ }
+ this.thrower = thrower;
+ this.dropped = Math.min(this.argsCount, catchDrops);
+ catcher = testCase.getCatcher(getCatcherParams());
+ nargs = Math.max(2, this.argsCount);
+ }
+
+ public static void main(String[] args) throws Throwable {
+ for (CatchExceptionTest test : TestFactory.MANDATORY_TEST_CASES) {
+ test.runTest();
+ }
+ TestFactory factory = new TestFactory();
+ CatchExceptionTest test;
+ while ((test = factory.nextTest()) != null ) {
+ test.runTest();
+ }
+ }
+
+ private List<Class<?>> getThrowerParams(boolean isVararg, int argsCount) {
+ boolean unmodifiable = true;
+ List<Class<?>> classes;
+ classes = ARGS_CLASSES.subList(0,
+ Math.min(argsCount, (MAX_ARITY / 2) - 1));
+ int extra = 0;
+ if (argsCount >= MAX_ARITY / 2) {
+ classes = new ArrayList<>(classes);
+ unmodifiable = false;
+ extra = (int) classes.stream().filter(Helper::isDoubleCost).count();
+ int i = classes.size();
+ while (classes.size() + extra < argsCount) {
+ Class<?> aClass = ARGS_CLASSES.get(i);
+ if (Helper.isDoubleCost(aClass)) {
+ ++extra;
+ if (classes.size() + extra >= argsCount) {
+ break;
+ }
+ }
+ classes.add(aClass);
+ }
+ }
+ if (isVararg && classes.size() > 0) {
+ if (unmodifiable) {
+ classes = new ArrayList<>(classes);
+ }
+ int last = classes.size() - 1;
+ Class<?> aClass = classes.get(classes.size() - 1);
+ aClass = Array.newInstance(aClass, 2).getClass();
+ classes.set(last, aClass);
+ }
+ return classes;
+ }
+
+
+ private List<Class<?>> getCatcherParams() {
+ int catchArgc = 1 + this.argsCount - dropped;
+ List<Class<?>> result = new ArrayList<>(
+ thrower.type().parameterList().subList(0, catchArgc - 1));
+ // prepend throwable
+ result.add(0, testCase.throwableClass);
+ return result;
+ }
+
+ private void runTest() {
+ Helper.clear();
+
+ Object[] args = Helper.randomArgs(
+ argsCount, thrower.type().parameterArray());
+ Object arg0 = Helper.MISSING_ARG;
+ Object arg1 = testCase.thrown;
+ if (argsCount > 0) {
+ arg0 = args[0];
+ }
+ if (argsCount > 1) {
+ args[1] = arg1;
+ }
+ Asserts.assertEQ(nargs, thrower.type().parameterCount());
+ if (argsCount < nargs) {
+ Object[] appendArgs = {arg0, arg1};
+ appendArgs = Arrays.copyOfRange(appendArgs, argsCount, nargs);
+ thrower = MethodHandles.insertArguments(
+ thrower, argsCount, appendArgs);
+ }
+ Asserts.assertEQ(argsCount, thrower.type().parameterCount());
+
+ MethodHandle target = MethodHandles.catchException(
+ testCase.filter(thrower), testCase.throwableClass,
+ testCase.filter(catcher));
+
+ Asserts.assertEQ(thrower.type(), target.type());
+ Asserts.assertEQ(argsCount, target.type().parameterCount());
+
+ Object returned;
+ try {
+ returned = target.invokeWithArguments(args);
+ } catch (Throwable ex) {
+ testCase.assertCatch(ex);
+ returned = ex;
+ }
+
+ testCase.assertReturn(returned, arg0, arg1, dropped, args);
+ }
+}
+
+class TestFactory {
+ public static final List<CatchExceptionTest> MANDATORY_TEST_CASES = new ArrayList<>();
+
+ private static final int MIN_TESTED_ARITY = 10;
+
+ static {
+ for (int[] args : new int[][]{
+ {0, 0},
+ {MIN_TESTED_ARITY, 0},
+ {MIN_TESTED_ARITY, MIN_TESTED_ARITY},
+ {CatchExceptionTest.MAX_ARITY, 0},
+ {CatchExceptionTest.MAX_ARITY, CatchExceptionTest.MAX_ARITY},
+ }) {
+ MANDATORY_TEST_CASES.addAll(createTests(args[0], args[1]));
+ }
+ }
+
+ private int count;
+ private int args;
+ private int dropArgs;
+ private int currentMaxDrops;
+ private int maxArgs;
+ private int maxDrops;
+ private int constructor;
+ private int constructorSize;
+ private boolean isVararg;
+
+ public TestFactory() {
+ if (Helper.IS_THOROUGH) {
+ maxArgs = maxDrops = CatchExceptionTest.MAX_ARITY;
+ } else {
+ maxArgs = MIN_TESTED_ARITY
+ + Helper.RNG.nextInt(CatchExceptionTest.MAX_ARITY
+ - MIN_TESTED_ARITY)
+ + 1;
+ maxDrops = MIN_TESTED_ARITY
+ + Helper.RNG.nextInt(maxArgs - MIN_TESTED_ARITY)
+ + 1;
+ args = 1;
+ }
+
+ if (Helper.IS_VERBOSE) {
+ System.out.printf("maxArgs = %d%nmaxDrops = %d%n",
+ maxArgs, maxDrops);
+ }
+ constructorSize = TestCase.CONSTRUCTORS.size();
+ }
+
+ private static List<CatchExceptionTest> createTests(int argsCount,
+ int catchDrops) {
+ if (catchDrops > argsCount || argsCount < 0 || catchDrops < 0) {
+ throw new IllegalArgumentException("argsCount = " + argsCount
+ + ", catchDrops = " + catchDrops
+ );
+ }
+ List<CatchExceptionTest> result = new ArrayList<>(
+ TestCase.CONSTRUCTORS.size());
+ for (Supplier<TestCase> constructor : TestCase.CONSTRUCTORS) {
+ result.add(new CatchExceptionTest(constructor.get(),
+ /* isVararg = */ true,
+ argsCount,
+ catchDrops));
+ result.add(new CatchExceptionTest(constructor.get(),
+ /* isVararg = */ false,
+ argsCount,
+ catchDrops));
+ }
+ return result;
+ }
+
+ /**
+ * @return next test from test matrix:
+ * {varArgs, noVarArgs} x TestCase.rtypes x TestCase.THROWABLES x {1, .., maxArgs } x {1, .., maxDrops}
+ */
+ public CatchExceptionTest nextTest() {
+ if (constructor < constructorSize) {
+ return createTest();
+ }
+ constructor = 0;
+ count++;
+ if (!Helper.IS_THOROUGH && count > Helper.TEST_LIMIT) {
+ System.out.println("test limit is exceeded");
+ return null;
+ }
+ if (dropArgs <= currentMaxDrops) {
+ if (dropArgs == 1) {
+ if (Helper.IS_THOROUGH || Helper.RNG.nextBoolean()) {
+ ++dropArgs;
+ return createTest();
+ } else if (Helper.IS_VERBOSE) {
+ System.out.printf(
+ "argsCount=%d : \"drop\" scenarios are skipped%n",
+ args);
+ }
+ } else {
+ ++dropArgs;
+ return createTest();
+ }
+ }
+
+ if (args <= maxArgs) {
+ dropArgs = 1;
+ currentMaxDrops = Math.min(args, maxDrops);
+ ++args;
+ return createTest();
+ }
+ return null;
+ }
+
+ private CatchExceptionTest createTest() {
+ if (!Helper.IS_THOROUGH) {
+ return new CatchExceptionTest(
+ TestCase.CONSTRUCTORS.get(constructor++).get(),
+ Helper.RNG.nextBoolean(), args, dropArgs);
+ } else {
+ if (isVararg) {
+ isVararg = false;
+ return new CatchExceptionTest(
+ TestCase.CONSTRUCTORS.get(constructor++).get(),
+ isVararg, args, dropArgs);
+ } else {
+ isVararg = true;
+ return new CatchExceptionTest(
+ TestCase.CONSTRUCTORS.get(constructor).get(),
+ isVararg, args, dropArgs);
+ }
+ }
+ }
+}
+
+class TestCase<T> {
+ private static enum ThrowMode {
+ NOTHING,
+ CAUGHT,
+ UNCAUGHT,
+ ADAPTER
+ }
+
+ @SuppressWarnings("unchecked")
+ public static final List<Supplier<TestCase>> CONSTRUCTORS;
+ private static final MethodHandle FAKE_IDENTITY;
+ private static final MethodHandle THROW_OR_RETURN;
+ private static final MethodHandle CATCHER;
+
+ static {
+ try {
+ MethodHandles.Lookup lookup = MethodHandles.lookup();
+ THROW_OR_RETURN = lookup.findStatic(
+ TestCase.class,
+ "throwOrReturn",
+ MethodType.methodType(Object.class, Object.class,
+ Throwable.class)
+ );
+ CATCHER = lookup.findStatic(
+ TestCase.class,
+ "catcher",
+ MethodType.methodType(Object.class, Object.class));
+ FAKE_IDENTITY = lookup.findVirtual(
+ TestCase.class, "fakeIdentity",
+ MethodType.methodType(Object.class, Object.class));
+
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ throw new Error(e);
+ }
+ PartialConstructor[] constructors = {
+ create(Object.class, Object.class::cast),
+ create(String.class, Objects::toString),
+ create(int[].class, x -> new int[]{Objects.hashCode(x)}),
+ create(long.class,
+ x -> Objects.hashCode(x) & (-1L >>> 32)),
+ create(void.class, TestCase::noop)};
+ Throwable[] throwables = {
+ new ClassCastException("testing"),
+ new java.io.IOException("testing"),
+ new LinkageError("testing")};
+ List<Supplier<TestCase>> list = new ArrayList<>(constructors.length *
+ throwables.length * ThrowMode.values().length);
+ //noinspection unchecked
+ for (PartialConstructor f : constructors) {
+ for (ThrowMode mode : ThrowMode.values()) {
+ for (Throwable t : throwables) {
+ list.add(f.apply(mode, t));
+ }
+ }
+ }
+ CONSTRUCTORS = Collections.unmodifiableList(list);
+ }
+
+ public final Class<T> rtype;
+ public final ThrowMode throwMode;
+ public final Throwable thrown;
+ public final Class<? extends Throwable> throwableClass;
+ /**
+ * MH which takes 2 args (Object,Throwable), 1st is the return value,
+ * 2nd is the exception which will be thrown, if it's supposed in current
+ * {@link #throwMode}.
+ */
+ public final MethodHandle thrower;
+ private final Function<Object, T> cast;
+ protected MethodHandle filter;
+ private int fakeIdentityCount;
+
+ private TestCase(Class<T> rtype, Function<Object, T> cast,
+ ThrowMode throwMode, Throwable thrown)
+ throws NoSuchMethodException, IllegalAccessException {
+ this.cast = cast;
+ filter = MethodHandles.lookup().findVirtual(
+ Function.class,
+ "apply",
+ MethodType.methodType(Object.class, Object.class))
+ .bindTo(cast);
+ this.rtype = rtype;
+ this.throwMode = throwMode;
+ this.throwableClass = thrown.getClass();
+ switch (throwMode) {
+ case NOTHING:
+ this.thrown = null;
+ break;
+ case ADAPTER:
+ case UNCAUGHT:
+ this.thrown = new Error("do not catch this");
+ break;
+ default:
+ this.thrown = thrown;
+ }
+
+ MethodHandle throwOrReturn = THROW_OR_RETURN;
+ if (throwMode == ThrowMode.ADAPTER) {
+ MethodHandle fakeIdentity = FAKE_IDENTITY.bindTo(this);
+ for (int i = 0; i < 10; ++i) {
+ throwOrReturn = MethodHandles.filterReturnValue(
+ throwOrReturn, fakeIdentity);
+ }
+ }
+ thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
+ }
+
+ private static Void noop(Object x) {
+ return null;
+ }
+
+ private static <T2> PartialConstructor create(
+ Class<T2> rtype, Function<Object, T2> cast) {
+ return (t, u) -> () -> {
+ try {
+ return new TestCase<>(rtype, cast, t, u);
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ throw new Error(e);
+ }
+ };
+ }
+
+ private static <T extends Throwable>
+ Object throwOrReturn(Object normal, T exception) throws T {
+ if (exception != null) {
+ Helper.called("throwOrReturn/throw", normal, exception);
+ throw exception;
+ }
+ Helper.called("throwOrReturn/normal", normal, exception);
+ return normal;
+ }
+
+ private static <T extends Throwable>
+ Object catcher(Object o) {
+ Helper.called("catcher", o);
+ return o;
+ }
+
+ public MethodHandle filter(MethodHandle target) {
+ return MethodHandles.filterReturnValue(target, filter);
+ }
+
+ public MethodHandle getCatcher(List<Class<?>> classes) {
+ return MethodHandles.filterReturnValue(Helper.AS_LIST.asType(
+ MethodType.methodType(Object.class, classes)),
+ CATCHER
+ );
+ }
+
+ @Override
+ public String toString() {
+ return "TestCase{" +
+ "rtype=" + rtype +
+ ", throwMode=" + throwMode +
+ ", throwableClass=" + throwableClass +
+ '}';
+ }
+
+ public String callName() {
+ return "throwOrReturn/" +
+ (throwMode == ThrowMode.NOTHING
+ ? "normal"
+ : "throw");
+ }
+
+ public void assertReturn(Object returned, Object arg0, Object arg1,
+ int catchDrops, Object... args) {
+ int lag = 0;
+ if (throwMode == ThrowMode.CAUGHT) {
+ lag = 1;
+ }
+ Helper.assertCalled(lag, callName(), arg0, arg1);
+
+ if (throwMode == ThrowMode.NOTHING) {
+ assertEQ(cast.apply(arg0), returned);
+ } else if (throwMode == ThrowMode.CAUGHT) {
+ List<Object> catchArgs = new ArrayList<>(Arrays.asList(args));
+ // catcher receives an initial subsequence of target arguments:
+ catchArgs.subList(args.length - catchDrops, args.length).clear();
+ // catcher also receives the exception, prepended:
+ catchArgs.add(0, thrown);
+ Helper.assertCalled("catcher", catchArgs);
+ assertEQ(cast.apply(catchArgs), returned);
+ }
+ Asserts.assertEQ(0, fakeIdentityCount);
+ }
+
+ private void assertEQ(T t, Object returned) {
+ if (rtype.isArray()) {
+ Asserts.assertEQ(t.getClass(), returned.getClass());
+ int n = Array.getLength(t);
+ Asserts.assertEQ(n, Array.getLength(returned));
+ for (int i = 0; i < n; ++i) {
+ Asserts.assertEQ(Array.get(t, i), Array.get(returned, i));
+ }
+ } else {
+ Asserts.assertEQ(t, returned);
+ }
+ }
+
+ private Object fakeIdentity(Object x) {
+ System.out.println("should throw through this!");
+ ++fakeIdentityCount;
+ return x;
+ }
+
+ public void assertCatch(Throwable ex) {
+ try {
+ Asserts.assertSame(thrown, ex,
+ "must get the out-of-band exception");
+ } catch (Throwable t) {
+ ex.printStackTrace();
+ }
+ }
+
+ public interface PartialConstructor
+ extends BiFunction<ThrowMode, Throwable, Supplier<TestCase>> {
+ }
+}
diff --git a/jdk/test/java/lang/invoke/MethodHandles/TestCatchException.java b/jdk/test/java/lang/invoke/MethodHandles/TestCatchException.java
index 106eafc..8197129 100644
--- a/jdk/test/java/lang/invoke/MethodHandles/TestCatchException.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/TestCatchException.java
@@ -72,10 +72,99 @@
assertEquals(x, 17);
}
+ final static Object masterParam = new Object();
+ final static Object[] masterTail = new Object[] { "str" };
+ static Exception masterEx = new Exception();
+
+ public static Object m1(Object o1, Object o2, Object o3, Object o4, Object o5,
+ Object o6, Object o7, Object o8, Object... tail) {
+ assertEquals(masterParam, o1);
+ assertEquals(masterParam, o2);
+ assertEquals(masterParam, o3);
+ assertEquals(masterParam, o4);
+ assertEquals(masterParam, o5);
+ assertEquals(masterParam, o6);
+ assertEquals(masterParam, o7);
+ assertEquals(masterParam, o8);
+ assertEquals(masterTail, tail);
+ return tail;
+ }
+
+ public static Object m2(Exception e, Object o1, Object o2, Object o3, Object o4,
+ Object o5, Object o6, Object o7, Object o8, Object... tail) {
+ assertEquals(masterEx, e);
+ assertEquals(masterParam, o1);
+ assertEquals(masterParam, o2);
+ assertEquals(masterParam, o3);
+ assertEquals(masterParam, o4);
+ assertEquals(masterParam, o5);
+ assertEquals(masterParam, o6);
+ assertEquals(masterParam, o7);
+ assertEquals(masterParam, o8);
+ assertEquals(masterTail, tail);
+ return tail;
+ }
+
+ public static Object throwEx(Object o1, Object o2, Object o3, Object o4, Object o5,
+ Object o6, Object o7, Object o8, Object... tail) throws Exception {
+ assertEquals(masterParam, o1);
+ assertEquals(masterParam, o2);
+ assertEquals(masterParam, o3);
+ assertEquals(masterParam, o4);
+ assertEquals(masterParam, o5);
+ assertEquals(masterParam, o6);
+ assertEquals(masterParam, o7);
+ assertEquals(masterParam, o8);
+ assertEquals(masterTail, tail);
+ throw masterEx;
+ }
+
+ @Test
+ public void testVarargsCollectorNoThrow() throws Throwable {
+ MethodType t1 = MethodType.methodType(Object.class, Object.class, Object.class, Object.class, Object.class,
+ Object.class, Object.class, Object.class, Object.class, Object[].class);
+
+ MethodType t2 = t1.insertParameterTypes(0, Exception.class);
+
+ MethodHandle target = LOOKUP.findStatic(TestCatchException.class, "m1", t1)
+ .asVarargsCollector(Object[].class);
+ MethodHandle catcher = LOOKUP.findStatic(TestCatchException.class, "m2", t2)
+ .asVarargsCollector(Object[].class);
+ MethodHandle gwc = MethodHandles.catchException(target, Exception.class, catcher);
+
+ Object o = masterParam;
+ Object[] obj1 = masterTail;
+
+ Object r2 = gwc.invokeExact(o, o, o, o, o, o, o, o, obj1);
+ assertEquals(r2, obj1);
+ }
+
+ @Test
+ public void testVarargsCollectorThrow() throws Throwable {
+ MethodType t1 = MethodType.methodType(Object.class, Object.class, Object.class, Object.class, Object.class,
+ Object.class, Object.class, Object.class, Object.class, Object[].class);
+
+ MethodType t2 = t1.insertParameterTypes(0, Exception.class);
+
+ MethodHandle target = LOOKUP.findStatic(TestCatchException.class, "throwEx", t1)
+ .asVarargsCollector(Object[].class);
+ MethodHandle catcher = LOOKUP.findStatic(TestCatchException.class, "m2", t2)
+ .asVarargsCollector(Object[].class);
+ MethodHandle gwc = MethodHandles.catchException(target, Exception.class, catcher);
+
+ Object o = masterParam;
+ Object[] obj1 = masterTail;
+
+ Object r2 = gwc.invokeExact(o, o, o, o, o, o, o, o, obj1);
+ assertEquals(r2, obj1);
+ }
+
public static void main(String[] args) throws Throwable {
TestCatchException test = new TestCatchException();
test.testNoThrowPath();
test.testThrowPath();
+ test.testVarargsCollectorNoThrow();
+ test.testVarargsCollectorThrow();
System.out.println("TEST PASSED");
}
}
diff --git a/jdk/test/java/lang/invoke/MethodHandlesTest.java b/jdk/test/java/lang/invoke/MethodHandlesTest.java
index a16adc2..d607e06 100644
--- a/jdk/test/java/lang/invoke/MethodHandlesTest.java
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java
@@ -2406,108 +2406,6 @@
}
@Test
- public void testCatchException() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("catchException");
- for (int nargs = 0; nargs < 40; nargs++) {
- if (CAN_TEST_LIGHTLY && nargs > 11) break;
- for (int throwMode = 0; throwMode < THROW_MODE_LIMIT; throwMode++) {
- testCatchException(int.class, new ClassCastException("testing"), throwMode, nargs);
- if (CAN_TEST_LIGHTLY && nargs > 3) continue;
- testCatchException(void.class, new java.io.IOException("testing"), throwMode, nargs);
- testCatchException(String.class, new LinkageError("testing"), throwMode, nargs);
- }
- }
- }
-
- static final int THROW_NOTHING = 0, THROW_CAUGHT = 1, THROW_UNCAUGHT = 2, THROW_THROUGH_ADAPTER = 3, THROW_MODE_LIMIT = 4;
-
- void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs) throws Throwable {
- testCatchException(returnType, thrown, throwMode, nargs, 0);
- if (nargs <= 5 || nargs % 10 == 3) {
- for (int catchDrops = 1; catchDrops <= nargs; catchDrops++)
- testCatchException(returnType, thrown, throwMode, nargs, catchDrops);
- }
- }
-
- private static <T extends Throwable>
- Object throwOrReturn(Object normal, T exception) throws T {
- if (exception != null) {
- called("throwOrReturn/throw", normal, exception);
- throw exception;
- }
- called("throwOrReturn/normal", normal, exception);
- return normal;
- }
- private int fakeIdentityCount;
- private Object fakeIdentity(Object x) {
- System.out.println("should throw through this!");
- fakeIdentityCount++;
- return x;
- }
-
- void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs, int catchDrops) throws Throwable {
- countTest();
- if (verbosity >= 3)
- System.out.println("catchException rt="+returnType+" throw="+throwMode+" nargs="+nargs+" drops="+catchDrops);
- Class<? extends Throwable> exType = thrown.getClass();
- if (throwMode > THROW_CAUGHT) thrown = new UnsupportedOperationException("do not catch this");
- MethodHandle throwOrReturn
- = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
- MethodType.methodType(Object.class, Object.class, Throwable.class));
- if (throwMode == THROW_THROUGH_ADAPTER) {
- MethodHandle fakeIdentity
- = PRIVATE.findVirtual(MethodHandlesTest.class, "fakeIdentity",
- MethodType.methodType(Object.class, Object.class)).bindTo(this);
- for (int i = 0; i < 10; i++)
- throwOrReturn = MethodHandles.filterReturnValue(throwOrReturn, fakeIdentity);
- }
- int nargs1 = Math.max(2, nargs);
- MethodHandle thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
- thrower = addTrailingArgs(thrower, nargs, Object.class);
- int catchArgc = 1 + nargs - catchDrops;
- MethodHandle catcher = varargsList(catchArgc).asType(MethodType.genericMethodType(catchArgc));
- Object[] args = randomArgs(nargs, Object.class);
- Object arg0 = MISSING_ARG;
- Object arg1 = (throwMode == THROW_NOTHING) ? (Throwable) null : thrown;
- if (nargs > 0) arg0 = args[0];
- if (nargs > 1) args[1] = arg1;
- assertEquals(nargs1, thrower.type().parameterCount());
- if (nargs < nargs1) {
- Object[] appendArgs = { arg0, arg1 };
- appendArgs = Arrays.copyOfRange(appendArgs, nargs, nargs1);
- thrower = MethodHandles.insertArguments(thrower, nargs, appendArgs);
- }
- assertEquals(nargs, thrower.type().parameterCount());
- MethodHandle target = MethodHandles.catchException(thrower, exType, catcher);
- assertEquals(thrower.type(), target.type());
- assertEquals(nargs, target.type().parameterCount());
- //System.out.println("catching with "+target+" : "+throwOrReturn);
- Object returned;
- try {
- returned = target.invokeWithArguments(args);
- } catch (Throwable ex) {
- assertSame("must get the out-of-band exception", thrown, ex);
- if (throwMode <= THROW_CAUGHT)
- assertEquals(THROW_UNCAUGHT, throwMode);
- returned = ex;
- }
- assertCalled("throwOrReturn/"+(throwMode == THROW_NOTHING ? "normal" : "throw"), arg0, arg1);
- //System.out.println("return from "+target+" : "+returned);
- if (throwMode == THROW_NOTHING) {
- assertSame(arg0, returned);
- } else if (throwMode == THROW_CAUGHT) {
- List<Object> catchArgs = new ArrayList<>(Arrays.asList(args));
- // catcher receives an initial subsequence of target arguments:
- catchArgs.subList(nargs - catchDrops, nargs).clear();
- // catcher also receives the exception, prepended:
- catchArgs.add(0, thrown);
- assertEquals(catchArgs, returned);
- }
- assertEquals(0, fakeIdentityCount);
- }
-
- @Test
public void testThrowException() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("throwException");
diff --git a/jdk/test/java/util/Arrays/StreamAndSpliterator.java b/jdk/test/java/util/Arrays/StreamAndSpliterator.java
new file mode 100644
index 0000000..b475e7e
--- /dev/null
+++ b/jdk/test/java/util/Arrays/StreamAndSpliterator.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2014, 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 8037857
+ * @summary tests for stream and spliterator factory methods
+ * @run testng StreamAndSpliterator
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Spliterators;
+
+import static org.testng.Assert.assertNotNull;
+
+public class StreamAndSpliterator {
+ @Test
+ public void testStreamNPEs() {
+ assertThrowsNPE(() -> Arrays.stream((int[]) null, 0, 0));
+ assertThrowsNPE(() -> Arrays.stream((long[]) null, 0, 0));
+ assertThrowsNPE(() -> Arrays.stream((double[]) null, 0, 0));
+ assertThrowsNPE(() -> Arrays.stream((String[]) null, 0, 0));
+ }
+
+ @Test
+ public void testStreamAIOBEs() {
+ // origin > fence
+ assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, 1, 0));
+ assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, 1, 0));
+ assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, 1, 0));
+ assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, 1, 0));
+
+ // bad origin
+ assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, -1, 0));
+ assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, -1, 0));
+ assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, -1, 0));
+ assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, -1, 0));
+
+ // bad fence
+ assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, 0, 1));
+ assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, 0, 1));
+ assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, 0, 1));
+ assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, 0, 1));
+ }
+
+
+ @Test
+ public void testSpliteratorNPEs() {
+ assertThrowsNPE(() -> Arrays.spliterator((int[]) null, 0, 0));
+ assertThrowsNPE(() -> Arrays.spliterator((long[]) null, 0, 0));
+ assertThrowsNPE(() -> Arrays.spliterator((double[]) null, 0, 0));
+ assertThrowsNPE(() -> Arrays.spliterator((String[]) null, 0, 0));
+ }
+
+ @Test
+ public void testSpliteratorAIOBEs() {
+ // origin > fence
+ assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, 1, 0));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, 1, 0));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, 1, 0));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, 1, 0));
+
+ // bad origin
+ assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, -1, 0));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, -1, 0));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, -1, 0));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, -1, 0));
+
+ // bad fence
+ assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, 0, 1));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, 0, 1));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, 0, 1));
+ assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, 0, 1));
+ }
+
+
+ @Test
+ public void testSpliteratorNPEsFromSpliterators() {
+ assertThrowsNPE(() -> Spliterators.spliterator((int[]) null, 0, 0, 0));
+ assertThrowsNPE(() -> Spliterators.spliterator((long[]) null, 0, 0, 0));
+ assertThrowsNPE(() -> Spliterators.spliterator((double[]) null, 0, 0, 0));
+ assertThrowsNPE(() -> Spliterators.spliterator((String[]) null, 0, 0, 0));
+ }
+
+ @Test
+ public void testSpliteratorAIOBEsFromSpliterators() {
+ // origin > fence
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, 1, 0, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, 1, 0, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, 1, 0, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 1, 0, 0));
+
+ // bad origin
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, -1, 0, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, -1, 0, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, -1, 0, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, -1, 0, 0));
+
+ // bad fence
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, 0, 1, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, 0, 1, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, 0, 1, 0));
+ assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 0, 1, 0));
+ }
+
+ void assertThrowsNPE(Runnable r) {
+ NullPointerException caught = null;
+ try {
+ r.run();
+ }
+ catch (NullPointerException e) {
+ caught = e;
+ }
+ assertNotNull(caught, "NullPointerException not thrown");
+ }
+
+ void assertThrowsAIOOB(Runnable r) {
+ ArrayIndexOutOfBoundsException caught = null;
+ try {
+ r.run();
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ caught = e;
+ }
+ assertNotNull(caught, "ArrayIndexOutOfBoundsException not thrown");
+ }
+}
diff --git a/jdk/test/java/util/Collection/CollectionDefaults.java b/jdk/test/java/util/Collection/CollectionDefaults.java
index bbfd330..c2d147f 100644
--- a/jdk/test/java/util/Collection/CollectionDefaults.java
+++ b/jdk/test/java/util/Collection/CollectionDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -21,6 +21,7 @@
* questions.
*/
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -44,8 +45,8 @@
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.function.Function;
import java.util.function.Predicate;
-import java.util.function.Supplier;
/**
* @test
@@ -59,26 +60,25 @@
public static final Predicate<Integer> pEven = x -> 0 == x % 2;
public static final Predicate<Integer> pOdd = x -> 1 == x % 2;
- @SuppressWarnings("unchecked")
- private static final Supplier<?>[] TEST_CLASSES = {
- // Collection
- ExtendsAbstractCollection<Integer>::new,
+ private static final List<Function<Collection<Integer>, Collection<Integer>>> TEST_SUPPLIERS = Arrays.asList(
+ // Collection
+ ExtendsAbstractCollection<Integer>::new,
- // Lists
- java.util.ArrayList<Integer>::new,
- java.util.LinkedList<Integer>::new,
- java.util.Vector<Integer>::new,
- java.util.concurrent.CopyOnWriteArrayList<Integer>::new,
- ExtendsAbstractList<Integer>::new,
+ // Lists
+ java.util.ArrayList<Integer>::new,
+ java.util.LinkedList<Integer>::new,
+ java.util.Vector<Integer>::new,
+ java.util.concurrent.CopyOnWriteArrayList<Integer>::new,
+ ExtendsAbstractList<Integer>::new,
- // Sets
- java.util.HashSet<Integer>::new,
- java.util.LinkedHashSet<Integer>::new,
- java.util.TreeSet<Integer>::new,
- java.util.concurrent.ConcurrentSkipListSet<Integer>::new,
- java.util.concurrent.CopyOnWriteArraySet<Integer>::new,
- ExtendsAbstractSet<Integer>::new
- };
+ // Sets
+ java.util.HashSet<Integer>::new,
+ java.util.LinkedHashSet<Integer>::new,
+ java.util.TreeSet<Integer>::new,
+ java.util.concurrent.ConcurrentSkipListSet<Integer>::new,
+ java.util.concurrent.CopyOnWriteArraySet<Integer>::new,
+ ExtendsAbstractSet<Integer>::new
+ );
private static final int SIZE = 100;
@@ -94,7 +94,7 @@
cases.add(new Object[] { new ExtendsAbstractSet<>() });
cases.add(new Object[] { Collections.newSetFromMap(new HashMap<>()) });
- cases.add(new Object[] { Collections.newSetFromMap(new LinkedHashMap()) });
+ cases.add(new Object[] { Collections.newSetFromMap(new LinkedHashMap<>()) });
cases.add(new Object[] { Collections.newSetFromMap(new TreeMap<>()) });
cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentHashMap<>()) });
cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentSkipListMap<>()) });
@@ -107,24 +107,23 @@
}
@Test(dataProvider = "setProvider")
- public void testProvidedWithNull(final Set<Integer> set) throws Exception {
+ public void testProvidedWithNull(final Set<Integer> set) {
try {
set.forEach(null);
fail("expected NPE not thrown");
- } catch (NullPointerException expected) {
- ; // expected
- }
+ } catch (NullPointerException expected) { // expected
+ }
try {
set.removeIf(null);
fail("expected NPE not thrown");
- } catch (NullPointerException expected) {
- ; // expected
+ } catch (NullPointerException expected) { // expected
}
}
@Test
- public void testForEach() throws Exception {
- final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier((Supplier<Collection<Integer>>[]) TEST_CLASSES, SIZE);
+ public void testForEach() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier(TEST_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) {
final Collection<Integer> original = test.expected;
@@ -133,8 +132,7 @@
try {
set.forEach(null);
fail("expected NPE not thrown");
- } catch (NullPointerException expected) {
- ; // expected
+ } catch (NullPointerException expected) { // expected
}
if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) {
CollectionAsserts.assertContentsUnordered(set, original, test.toString());
@@ -155,8 +153,9 @@
}
@Test
- public void testRemoveIf() throws Exception {
- final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier((Supplier<Collection<Integer>>[]) TEST_CLASSES, SIZE);
+ public void testRemoveIf() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier(TEST_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) {
final Collection<Integer> original = test.expected;
final Collection<Integer> set = test.collection;
@@ -164,8 +163,7 @@
try {
set.removeIf(null);
fail("expected NPE not thrown");
- } catch (NullPointerException expected) {
- ; // expected
+ } catch (NullPointerException expected) { // expected
}
if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) {
CollectionAsserts.assertContentsUnordered(set, original, test.toString());
diff --git a/jdk/test/java/util/Collection/testlibrary/CollectionSupplier.java b/jdk/test/java/util/Collection/testlibrary/CollectionSupplier.java
index 4a8b735..714bc73 100644
--- a/jdk/test/java/util/Collection/testlibrary/CollectionSupplier.java
+++ b/jdk/test/java/util/Collection/testlibrary/CollectionSupplier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -25,6 +25,7 @@
import java.lang.Integer;
import java.lang.Iterable;
import java.lang.Override;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@@ -36,6 +37,7 @@
import java.util.Collection;
import java.util.Collections;
+import java.util.function.Function;
import java.util.function.Supplier;
/**
@@ -44,20 +46,24 @@
*/
public final class CollectionSupplier<C extends Collection<Integer>> implements Supplier<Iterable<CollectionSupplier.TestCase<C>>> {
- private final Supplier<C>[] classes;
+ private final List<Function<Collection<Integer>, C>> suppliers;
private final int size;
/**
* A Collection test case.
*/
public static final class TestCase<C extends Collection<Integer>> {
-
/**
* The name of the test case.
*/
public final String name;
/**
+ * The supplier of a collection
+ */
+ public Function<Collection<Integer>, C> supplier;
+
+ /**
* Unmodifiable reference collection, useful for comparisons.
*/
public final List<Integer> expected;
@@ -71,11 +77,11 @@
* Create a Collection test case.
*
* @param name name of the test case
- * @param expected reference collection
* @param collection the modifiable test collection
*/
- public TestCase(String name, C collection) {
+ public TestCase(String name, Function<Collection<Integer>, C> supplier, C collection) {
this.name = name;
+ this.supplier = supplier;
this.expected = Collections.unmodifiableList(
Arrays.asList(collection.toArray(new Integer[0])));
this.collection = collection;
@@ -107,54 +113,52 @@
}
/**
- * Create a {@code Supplier} that creates instances of specified collection
- * classes of specified length.
+ * Create a {@code CollectionSupplier} that creates instances of specified
+ * collection suppliers of the specified size.
*
- * @param classNames class names that implement {@code Collection}
+ * @param suppliers the suppliers names that supply {@code Collection}
+ * instances
* @param size the desired size of each collection
*/
- public CollectionSupplier(Supplier<C>[] classes, int size) {
- this.classes = Arrays.copyOf(classes, classes.length);
+ public CollectionSupplier(List<Function<Collection<Integer>, C>> suppliers, int size) {
+ this.suppliers = suppliers;
this.size = size;
}
@Override
public Iterable<TestCase<C>> get() {
final Collection<TestCase<C>> cases = new LinkedList<>();
- for (final Supplier<C> type : classes) {
+ for (final Function<Collection<Integer>, C> supplier : suppliers)
try {
- final Collection<Integer> empty = type.get();
- cases.add(new TestCase("empty", empty));
+ cases.add(new TestCase<>("empty", supplier, supplier.apply(Collections.emptyList())));
- final Collection<Integer> single = type.get();
- single.add(42);
- cases.add(new TestCase("single", single));
+ cases.add(new TestCase<>("single", supplier, supplier.apply(Arrays.asList(42))));
- final Collection<Integer> regular = type.get();
+ final Collection<Integer> regular = new ArrayList<>();
for (int i = 0; i < size; i++) {
regular.add(i);
}
- cases.add(new TestCase("regular", regular));
+ cases.add(new TestCase<>("regular", supplier, supplier.apply(regular)));
- final Collection<Integer> reverse = type.get();
+ final Collection<Integer> reverse = new ArrayList<>();
for (int i = size; i >= 0; i--) {
reverse.add(i);
}
- cases.add(new TestCase("reverse", reverse));
+ cases.add(new TestCase<>("reverse", supplier, supplier.apply(reverse)));
- final Collection<Integer> odds = type.get();
+ final Collection<Integer> odds = new ArrayList<>();
for (int i = 0; i < size; i++) {
odds.add((i * 2) + 1);
}
- cases.add(new TestCase("odds", odds));
+ cases.add(new TestCase<>("odds", supplier, supplier.apply(odds)));
- final Collection<Integer> evens = type.get();
+ final Collection<Integer> evens = new ArrayList<>();
for (int i = 0; i < size; i++) {
evens.add(i * 2);
}
- cases.add(new TestCase("evens", evens));
+ cases.add(new TestCase<>("evens", supplier, supplier.apply(evens)));
- final Collection<Integer> fibonacci = type.get();
+ final Collection<Integer> fibonacci = new ArrayList<>();
int prev2 = 0;
int prev1 = 1;
for (int i = 0; i < size; i++) {
@@ -166,58 +170,62 @@
prev2 = prev1;
prev1 = n;
}
- cases.add(new TestCase("fibonacci", fibonacci));
+ cases.add(new TestCase<>("fibonacci", supplier, supplier.apply(fibonacci)));
- // variants where the size of the backing storage != reported size
+
+ boolean isStructurallyModifiable = false;
+ try {
+ C t = supplier.apply(Collections.emptyList());
+ t.add(1);
+ isStructurallyModifiable = true;
+ } catch (UnsupportedOperationException e) { }
+
+ if (!isStructurallyModifiable)
+ continue;
+
+
+ // variants where the size of the backing storage != reported size
// created by removing half of the elements
- final Collection<Integer> emptyWithSlack = type.get();
+ final C emptyWithSlack = supplier.apply(Collections.emptyList());
emptyWithSlack.add(42);
assertTrue(emptyWithSlack.remove(42));
- cases.add(new TestCase("emptyWithSlack", emptyWithSlack));
+ cases.add(new TestCase<>("emptyWithSlack", supplier, emptyWithSlack));
- final Collection<Integer> singleWithSlack = type.get();
+ final C singleWithSlack = supplier.apply(Collections.emptyList());
singleWithSlack.add(42);
singleWithSlack.add(43);
assertTrue(singleWithSlack.remove(43));
- cases.add(new TestCase("singleWithSlack", singleWithSlack));
+ cases.add(new TestCase<>("singleWithSlack", supplier, singleWithSlack));
- final Collection<Integer> regularWithSlack = type.get();
+ final C regularWithSlack = supplier.apply(Collections.emptyList());
for (int i = 0; i < (2 * size); i++) {
regularWithSlack.add(i);
}
- assertTrue(regularWithSlack.removeIf((x) -> {
- return x >= size;
- }));
- cases.add(new TestCase("regularWithSlack", regularWithSlack));
+ assertTrue(regularWithSlack.removeIf(x -> x < size));
+ cases.add(new TestCase<>("regularWithSlack", supplier, regularWithSlack));
- final Collection<Integer> reverseWithSlack = type.get();
+ final C reverseWithSlack = supplier.apply(Collections.emptyList());
for (int i = 2 * size; i >= 0; i--) {
reverseWithSlack.add(i);
}
- assertTrue(reverseWithSlack.removeIf((x) -> {
- return x < size;
- }));
- cases.add(new TestCase("reverseWithSlack", reverseWithSlack));
+ assertTrue(reverseWithSlack.removeIf(x -> x < size));
+ cases.add(new TestCase<>("reverseWithSlack", supplier, reverseWithSlack));
- final Collection<Integer> oddsWithSlack = type.get();
+ final C oddsWithSlack = supplier.apply(Collections.emptyList());
for (int i = 0; i < 2 * size; i++) {
oddsWithSlack.add((i * 2) + 1);
}
- assertTrue(oddsWithSlack.removeIf((x) -> {
- return x >= size;
- }));
- cases.add(new TestCase("oddsWithSlack", oddsWithSlack));
+ assertTrue(oddsWithSlack.removeIf(x -> x >= size));
+ cases.add(new TestCase<>("oddsWithSlack", supplier, oddsWithSlack));
- final Collection<Integer> evensWithSlack = type.get();
+ final C evensWithSlack = supplier.apply(Collections.emptyList());
for (int i = 0; i < 2 * size; i++) {
evensWithSlack.add(i * 2);
}
- assertTrue(evensWithSlack.removeIf((x) -> {
- return x >= size;
- }));
- cases.add(new TestCase("evensWithSlack", evensWithSlack));
+ assertTrue(evensWithSlack.removeIf(x -> x >= size));
+ cases.add(new TestCase<>("evensWithSlack", supplier, evensWithSlack));
- final Collection<Integer> fibonacciWithSlack = type.get();
+ final C fibonacciWithSlack = supplier.apply(Collections.emptyList());
prev2 = 0;
prev1 = 1;
for (int i = 0; i < size; i++) {
@@ -229,15 +237,12 @@
prev2 = prev1;
prev1 = n;
}
- assertTrue(fibonacciWithSlack.removeIf((x) -> {
- return x < 20;
- }));
- cases.add(new TestCase("fibonacciWithSlack",
- fibonacciWithSlack));
- } catch (Exception failed) {
+ assertTrue(fibonacciWithSlack.removeIf(x -> x < 20));
+ cases.add(new TestCase<>("fibonacciWithSlack", supplier, fibonacciWithSlack));
+ }
+ catch (Exception failed) {
throw new TestException(failed);
}
- }
return cases;
}
diff --git a/jdk/test/java/util/List/ListDefaults.java b/jdk/test/java/util/List/ListDefaults.java
index 8e36d5f..2d5260e 100644
--- a/jdk/test/java/util/List/ListDefaults.java
+++ b/jdk/test/java/util/List/ListDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -23,6 +23,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -43,31 +44,45 @@
import java.lang.reflect.Constructor;
import java.util.ConcurrentModificationException;
+import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* @test
* @summary Unit tests for extension methods on List
- * @bug 8023367
+ * @bug 8023367 8037106
* @library ../Collection/testlibrary
* @build CollectionAsserts CollectionSupplier ExtendsAbstractList
* @run testng ListDefaults
*/
public class ListDefaults {
- private static final Supplier<?>[] LIST_CLASSES = {
- java.util.ArrayList::new,
- java.util.LinkedList::new,
- java.util.Vector::new,
- java.util.concurrent.CopyOnWriteArrayList::new,
- ExtendsAbstractList::new
- };
+ // Suppliers of lists that can support structural modifications
+ private static final List<Function<Collection, List>> LIST_STRUCT_MOD_SUPPLIERS = Arrays.asList(
+ java.util.ArrayList::new,
+ java.util.LinkedList::new,
+ java.util.Vector::new,
+ java.util.concurrent.CopyOnWriteArrayList::new,
+ ExtendsAbstractList::new
+ );
- private static final Supplier<?>[] LIST_CME_CLASSES = {
- java.util.ArrayList::new,
- java.util.Vector::new
- };
+ // Suppliers of lists that can support in place modifications
+ private static final List<Function<Collection, List>> LIST_SUPPLIERS = Arrays.asList(
+ java.util.ArrayList::new,
+ java.util.LinkedList::new,
+ java.util.Vector::new,
+ java.util.concurrent.CopyOnWriteArrayList::new,
+ ExtendsAbstractList::new,
+ c -> Arrays.asList(c.toArray())
+ );
+
+ // Suppliers of lists supporting CMEs
+ private static final List<Function<Collection, List>> LIST_CME_SUPPLIERS = Arrays.asList(
+ java.util.ArrayList::new,
+ java.util.Vector::new
+ );
private static final Predicate<Integer> pEven = x -> 0 == x % 2;
private static final Predicate<Integer> pOdd = x -> 1 == x % 2;
@@ -83,17 +98,13 @@
private static final int SUBLIST_TO = SIZE - 5;
private static final int SUBLIST_SIZE = SUBLIST_TO - SUBLIST_FROM;
- private static interface Callback {
- void call(List<Integer> list);
- }
-
// call the callback for each recursive subList
- private void trimmedSubList(final List<Integer> list, final Callback callback) {
+ private void trimmedSubList(final List<Integer> list, final Consumer<List<Integer>> callback) {
int size = list.size();
if (size > 1) {
// trim 1 element from both ends
final List<Integer> subList = list.subList(1, size - 1);
- callback.call(subList);
+ callback.accept(subList);
trimmedSubList(subList, callback);
}
}
@@ -107,17 +118,21 @@
cases.add(new Object[] { new Vector<>() });
cases.add(new Object[] { new Stack<>() });
cases.add(new Object[] { new CopyOnWriteArrayList<>() });
+ cases.add(new Object[] { Arrays.asList() });
- cases.add(new Object[] { new ArrayList(){{add(42);}} });
- cases.add(new Object[] { new LinkedList(){{add(42);}} });
- cases.add(new Object[] { new Vector(){{add(42);}} });
- cases.add(new Object[] { new Stack(){{add(42);}} });
- cases.add(new Object[] { new CopyOnWriteArrayList(){{add(42);}} });
+ List<Integer> l = Arrays.asList(42);
+ cases.add(new Object[] { new ArrayList<>(l) });
+ cases.add(new Object[] { new LinkedList<>(l) });
+ cases.add(new Object[] { new Vector<>(l) });
+ Stack<Integer> s = new Stack<>(); s.addAll(l);
+ cases.add(new Object[]{s});
+ cases.add(new Object[] { new CopyOnWriteArrayList<>(l) });
+ cases.add(new Object[] { l });
return cases.toArray(new Object[0][cases.size()]);
}
@Test(dataProvider = "listProvider")
- public void testProvidedWithNull(final List<Integer> list) throws Exception {
+ public void testProvidedWithNull(final List<Integer> list) {
try {
list.forEach(null);
fail("expected NPE not thrown");
@@ -138,11 +153,12 @@
}
@Test
- public void testForEach() throws Exception {
- final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE);
+ public void testForEach() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
- final List<Integer> original = ((List<Integer>) test.expected);
- final List<Integer> list = ((List<Integer>) test.collection);
+ final List<Integer> original = test.expected;
+ final List<Integer> list = test.collection;
try {
list.forEach(null);
@@ -165,23 +181,21 @@
}
}
- trimmedSubList(list, new Callback() {
- @Override
- public void call(final List<Integer> list) {
- final List<Integer> actual = new LinkedList<>();
- list.forEach(actual::add);
- CollectionAsserts.assertContents(actual, list);
- }
- });
+ trimmedSubList(list, l -> {
+ final List<Integer> a = new LinkedList<>();
+ l.forEach(a::add);
+ CollectionAsserts.assertContents(a, l);
+ });
}
}
@Test
- public void testRemoveIf() throws Exception {
- final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE);
+ public void testRemoveIf() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_STRUCT_MOD_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
- final List<Integer> original = ((List<Integer>) test.expected);
- final List<Integer> list = ((List<Integer>) test.collection);
+ final List<Integer> original = test.expected;
+ final List<Integer> list = test.collection;
try {
list.removeIf(null);
@@ -195,9 +209,9 @@
}
}
- for (final CollectionSupplier.TestCase test : supplier.get()) {
- final List<Integer> original = ((List<Integer>) test.expected);
- final List<Integer> list = ((List<Integer>) test.collection);
+ for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+ final List<Integer> original = test.expected;
+ final List<Integer> list = test.collection;
list.removeIf(pOdd);
for (int i : list) {
assertTrue((i % 2) == 0);
@@ -211,9 +225,9 @@
assertTrue(list.isEmpty());
}
- for (final CollectionSupplier.TestCase test : supplier.get()) {
- final List<Integer> original = ((List<Integer>) test.expected);
- final List<Integer> list = ((List<Integer>) test.collection);
+ for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+ final List<Integer> original = test.expected;
+ final List<Integer> list = test.collection;
final List<Integer> listCopy = new ArrayList<>(list);
if (original.size() > SUBLIST_SIZE) {
final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
@@ -237,22 +251,19 @@
}
}
- for (final CollectionSupplier.TestCase test : supplier.get()) {
- final List<Integer> list = ((List<Integer>) test.collection);
- trimmedSubList(list, new Callback() {
- @Override
- public void call(final List<Integer> list) {
- final List<Integer> copy = new ArrayList<>(list);
- list.removeIf(pOdd);
- for (int i : list) {
- assertTrue((i % 2) == 0);
- }
- for (int i : copy) {
- if (i % 2 == 0) {
- assertTrue(list.contains(i));
- } else {
- assertFalse(list.contains(i));
- }
+ for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+ final List<Integer> list = test.collection;
+ trimmedSubList(list, l -> {
+ final List<Integer> copy = new ArrayList<>(l);
+ l.removeIf(pOdd);
+ for (int i : l) {
+ assertTrue((i % 2) == 0);
+ }
+ for (int i : copy) {
+ if (i % 2 == 0) {
+ assertTrue(l.contains(i));
+ } else {
+ assertFalse(l.contains(i));
}
}
});
@@ -267,12 +278,13 @@
}
@Test
- public void testReplaceAll() throws Exception {
+ public void testReplaceAll() {
final int scale = 3;
- final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE);
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
- final List<Integer> original = ((List<Integer>) test.expected);
- final List<Integer> list = ((List<Integer>) test.collection);
+ final List<Integer> original = test.expected;
+ final List<Integer> list = test.collection;
try {
list.replaceAll(null);
@@ -281,7 +293,7 @@
CollectionAsserts.assertContents(list, original);
list.replaceAll(x -> scale * x);
- for (int i=0; i < original.size(); i++) {
+ for (int i = 0; i < original.size(); i++) {
assertTrue(list.get(i) == (scale * original.get(i)), "mismatch at index " + i);
}
@@ -306,28 +318,26 @@
}
}
- for (final CollectionSupplier.TestCase test : supplier.get()) {
- final List<Integer> list = ((List<Integer>) test.collection);
- trimmedSubList(list, new Callback() {
- @Override
- public void call(final List<Integer> list) {
- final List<Integer> copy = new ArrayList<>(list);
- final int offset = 5;
- list.replaceAll(x -> offset + x);
- for (int i=0; i < copy.size(); i++) {
- assertTrue(list.get(i) == (offset + copy.get(i)), "mismatch at index " + i);
- }
+ for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+ final List<Integer> list = test.collection;
+ trimmedSubList(list, l -> {
+ final List<Integer> copy = new ArrayList<>(l);
+ final int offset = 5;
+ l.replaceAll(x -> offset + x);
+ for (int i = 0; i < copy.size(); i++) {
+ assertTrue(l.get(i) == (offset + copy.get(i)), "mismatch at index " + i);
}
});
}
}
@Test
- public void testSort() throws Exception {
- final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE);
+ public void testSort() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
- final List<Integer> original = ((List<Integer>) test.expected);
- final List<Integer> list = ((List<Integer>) test.collection);
+ final List<Integer> original = test.expected;
+ final List<Integer> list = test.collection;
CollectionSupplier.shuffle(list);
list.sort(Integer::compare);
CollectionAsserts.assertSorted(list, Integer::compare);
@@ -338,23 +348,23 @@
CollectionSupplier.shuffle(list);
list.sort(null);
- CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
+ CollectionAsserts.assertSorted(list, Comparator.naturalOrder());
if (test.name.startsWith("reverse")) {
Collections.reverse(list);
}
CollectionAsserts.assertContents(list, original);
CollectionSupplier.shuffle(list);
- list.sort(Comparator.<Integer>naturalOrder());
- CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
+ list.sort(Comparator.naturalOrder());
+ CollectionAsserts.assertSorted(list, Comparator.naturalOrder());
if (test.name.startsWith("reverse")) {
Collections.reverse(list);
}
CollectionAsserts.assertContents(list, original);
CollectionSupplier.shuffle(list);
- list.sort(Comparator.<Integer>reverseOrder());
- CollectionAsserts.assertSorted(list, Comparator.<Integer>reverseOrder());
+ list.sort(Comparator.reverseOrder());
+ CollectionAsserts.assertSorted(list, Comparator.reverseOrder());
if (!test.name.startsWith("reverse")) {
Collections.reverse(list);
}
@@ -365,32 +375,35 @@
CollectionAsserts.assertSorted(list, BIT_COUNT_COMPARATOR);
// check sort by verifying that bitCount increases and never drops
int minBitCount = 0;
- int bitCount = 0;
for (final Integer i : list) {
- bitCount = Integer.bitCount(i);
+ int bitCount = Integer.bitCount(i);
assertTrue(bitCount >= minBitCount);
minBitCount = bitCount;
}
- @SuppressWarnings("unchecked")
- final Constructor<? extends List<?>> defaultConstructor = ((Class<? extends List<?>>)test.collection.getClass()).getConstructor();
- final List<AtomicInteger> incomparables = (List<AtomicInteger>) defaultConstructor.newInstance();
-
- for (int i=0; i < test.expected.size(); i++) {
- incomparables.add(new AtomicInteger(i));
+ // Resuse the supplier to store AtomicInteger instead of Integer
+ // Hence the use of raw type and cast
+ List<AtomicInteger> incomparablesData = new ArrayList<>();
+ for (int i = 0; i < test.expected.size(); i++) {
+ incomparablesData.add(new AtomicInteger(i));
}
+ Function f = test.supplier;
+ @SuppressWarnings("unchecked")
+ List<AtomicInteger> incomparables = (List<AtomicInteger>) f.apply(incomparablesData);
+
CollectionSupplier.shuffle(incomparables);
incomparables.sort(ATOMIC_INTEGER_COMPARATOR);
- for (int i=0; i < test.expected.size(); i++) {
+ for (int i = 0; i < test.expected.size(); i++) {
assertEquals(i, incomparables.get(i).intValue());
}
+
if (original.size() > SUBLIST_SIZE) {
final List<Integer> copy = new ArrayList<>(list);
final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO);
CollectionSupplier.shuffle(subList);
- subList.sort(Comparator.<Integer>naturalOrder());
- CollectionAsserts.assertSorted(subList, Comparator.<Integer>naturalOrder());
+ subList.sort(Comparator.naturalOrder());
+ CollectionAsserts.assertSorted(subList, Comparator.naturalOrder());
// verify that elements [0, from) remain unmodified
for (int i = 0; i < SUBLIST_FROM; i++) {
assertTrue(list.get(i) == copy.get(i),
@@ -404,25 +417,22 @@
}
}
- for (final CollectionSupplier.TestCase test : supplier.get()) {
- final List<Integer> list = ((List<Integer>) test.collection);
- trimmedSubList(list, new Callback() {
- @Override
- public void call(final List<Integer> list) {
- final List<Integer> copy = new ArrayList<>(list);
- CollectionSupplier.shuffle(list);
- list.sort(Comparator.<Integer>naturalOrder());
- CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder());
- }
+ for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
+ final List<Integer> list = test.collection;
+ trimmedSubList(list, l -> {
+ CollectionSupplier.shuffle(l);
+ l.sort(Comparator.naturalOrder());
+ CollectionAsserts.assertSorted(l, Comparator.naturalOrder());
});
}
}
@Test
- public void testForEachThrowsCME() throws Exception {
- final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE);
+ public void testForEachThrowsCME() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
- final List<Integer> list = ((List<Integer>) test.collection);
+ final List<Integer> list = test.collection;
if (list.size() <= 1) {
continue;
@@ -430,7 +440,7 @@
boolean gotException = false;
try {
// bad predicate that modifies its list, should throw CME
- list.forEach((x) -> {list.add(x);});
+ list.forEach(list::add);
} catch (ConcurrentModificationException cme) {
gotException = true;
}
@@ -441,11 +451,11 @@
}
@Test
- public void testRemoveIfThrowsCME() throws Exception {
- final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE);
+ public void testRemoveIfThrowsCME() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
- final List<Integer> original = ((List<Integer>) test.expected);
- final List<Integer> list = ((List<Integer>) test.collection);
+ final List<Integer> list = test.collection;
if (list.size() <= 1) {
continue;
@@ -453,7 +463,7 @@
boolean gotException = false;
try {
// bad predicate that modifies its list, should throw CME
- list.removeIf((x) -> {return list.add(x);});
+ list.removeIf(list::add);
} catch (ConcurrentModificationException cme) {
gotException = true;
}
@@ -464,10 +474,11 @@
}
@Test
- public void testReplaceAllThrowsCME() throws Exception {
- final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE);
+ public void testReplaceAllThrowsCME() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
- final List<Integer> list = ((List<Integer>) test.collection);
+ final List<Integer> list = test.collection;
if (list.size() <= 1) {
continue;
@@ -486,10 +497,11 @@
}
@Test
- public void testSortThrowsCME() throws Exception {
- final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE);
+ public void testSortThrowsCME() {
+ @SuppressWarnings("unchecked")
+ final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE);
for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) {
- final List<Integer> list = ((List<Integer>) test.collection);
+ final List<Integer> list = test.collection;
if (list.size() <= 1) {
continue;
@@ -523,7 +535,7 @@
}
@Test(dataProvider = "shortIntListProvider")
- public void testRemoveIfFromSlice(final List<Integer> list) throws Exception {
+ public void testRemoveIfFromSlice(final List<Integer> list) {
final List<Integer> sublist = list.subList(3, 6);
assertTrue(sublist.removeIf(x -> x == 4));
CollectionAsserts.assertContents(list, SLICED_EXPECTED);
diff --git a/jdk/test/javax/swing/JComboBox/8032878/bug8032878.java b/jdk/test/javax/swing/JComboBox/8032878/bug8032878.java
new file mode 100644
index 0000000..f5c9c88
--- /dev/null
+++ b/jdk/test/javax/swing/JComboBox/8032878/bug8032878.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014, 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 8032878
+ * @summary Checks that JComboBox as JTable cell editor processes key events
+ * even where setSurrendersFocusOnKeystroke flag in JTable is false and
+ * that it does not lose the first key press where the flag is true.
+ * @library ../../regtesthelpers
+ * @build Util
+ * @author Alexey Ivanov
+ */
+
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import javax.swing.*;
+import javax.swing.text.JTextComponent;
+
+import sun.awt.SunToolkit;
+
+public class bug8032878 implements Runnable {
+ private static final String ONE = "one";
+ private static final String TWO = "two";
+ private static final String THREE = "three";
+
+ private static final String EXPECTED = "one123";
+
+ private final Robot robot;
+
+ private JFrame frame;
+ private JComboBox cb;
+
+ private volatile boolean surrender;
+ private volatile String text;
+
+ public static void main(String[] args) throws Exception {
+ final bug8032878 test = new bug8032878();
+
+ test.test(false);
+ test.test(true);
+ }
+
+ public bug8032878() throws AWTException {
+ robot = new Robot();
+ robot.setAutoDelay(100);
+ }
+
+ private void setupUI() {
+ frame = new JFrame();
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ JTable table = new JTable(new String[][] {{ONE}, {TWO}, {THREE}},
+ new String[] { "#"});
+ table.setSurrendersFocusOnKeystroke(surrender);
+
+ cb = new JComboBox(new String[]{ONE, TWO, THREE});
+ cb.setEditable(true);
+ DefaultCellEditor comboEditor = new DefaultCellEditor(cb);
+ comboEditor.setClickCountToStart(1);
+ table.getColumnModel().getColumn(0).setCellEditor(comboEditor);
+ frame.add(table);
+
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ private void test(final boolean flag) throws Exception {
+ try {
+ surrender = flag;
+ SwingUtilities.invokeAndWait(this);
+
+ runTest();
+ checkResult();
+ } finally {
+ if (frame != null) {
+ frame.dispose();
+ }
+ }
+ }
+
+ private void runTest() throws Exception {
+ realSync();
+ // Select 'one'
+ Util.hitKeys(robot, KeyEvent.VK_TAB);
+ realSync();
+ Util.hitKeys(robot, KeyEvent.VK_1);
+ Util.hitKeys(robot, KeyEvent.VK_2);
+ Util.hitKeys(robot, KeyEvent.VK_3);
+ Util.hitKeys(robot, KeyEvent.VK_ENTER);
+ realSync();
+ }
+
+ private void checkResult() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ text = ((JTextComponent) cb.getEditor().getEditorComponent()).getText();
+ }
+ });
+ if (text.equals(EXPECTED)) {
+ System.out.println("Test with surrender = " + surrender + " passed");
+ } else {
+ System.out.println("Test with surrender = " + surrender + " failed");
+ throw new RuntimeException("Expected value in JComboBox editor '" +
+ EXPECTED + "' but found '" + text + "'.");
+ }
+ }
+
+ private static void realSync() {
+ ((SunToolkit) (Toolkit.getDefaultToolkit())).realSync();
+ }
+
+ @Override
+ public void run() {
+ setupUI();
+ }
+}
diff --git a/jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.html b/jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.html
new file mode 100644
index 0000000..f9991a2
--- /dev/null
+++ b/jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.html
@@ -0,0 +1,30 @@
+<html>
+<!--
+ Copyright (c) 2014, 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.
+-->
+<body>
+<applet code="bug4984669.class" width=300 height=300></applet>
+The four lines printed above in a bold typeface should all be underlined.
+It is a bug if any of these lines is underlined only partially.
+The very first line should not be underlined at all.
+</body>
+</html>
diff --git a/jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.java b/jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.java
new file mode 100644
index 0000000..ba590f9
--- /dev/null
+++ b/jdk/test/javax/swing/text/GlyphView/4984669/bug4984669.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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 4984669 8002148
+ @summary Tests HTML underlining
+ @author Peter Zhelezniakov
+ @run applet/manual=yesno bug4984669.html
+*/
+import javax.swing.*;
+import javax.swing.text.*;
+
+public class bug4984669 extends JApplet
+{
+ public void init() {
+ JEditorPane pane = new JEditorPane();
+ this.getContentPane().add(new JScrollPane(pane));
+ pane.setEditorKit(new StyledEditorKit());
+
+ try {
+ pane.getDocument().insertString(0,"12 \n",null);
+ MutableAttributeSet attrs = new SimpleAttributeSet();
+
+ StyleConstants.setFontSize(attrs, 36);
+ StyleConstants.setBold(attrs, true);
+ StyleConstants.setUnderline(attrs, true);
+ pane.getDocument().insertString(6, "aa\n", attrs);
+ pane.getDocument().insertString(9, "bbb\n", attrs);
+ pane.getDocument().insertString(13, "cccc\n", attrs);
+ pane.getDocument().insertString(18, "ddddd\n", attrs);
+ } catch (Exception e) {
+ throw new Error("Failed: Unexpected Exception", e);
+ }
+ }
+}
diff --git a/jdk/test/javax/swing/text/html/8034955/bug8034955.java b/jdk/test/javax/swing/text/html/8034955/bug8034955.java
new file mode 100644
index 0000000..3e7bba2
--- /dev/null
+++ b/jdk/test/javax/swing/text/html/8034955/bug8034955.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 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 javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.SwingUtilities;
+
+/**
+ * @test
+ * @bug 8034955
+ * @author Alexander Scherbatiy
+ * @summary JLabel/JToolTip throw ClassCastException for "<html>a<title>"
+ * @run main bug8034955
+ */
+public class bug8034955 {
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ JFrame frame = new JFrame();
+ frame.getContentPane().add(new JLabel("<html>a<title>"));
+ frame.pack();
+ frame.setVisible(true);
+ }
+ });
+ }
+}
diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java b/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java
index d5e1361..794261e 100644
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java
@@ -23,6 +23,8 @@
package jdk.testlibrary;
+import java.util.Objects;
+
/**
* Asserts that can be used for verifying assumptions in tests.
*
@@ -171,6 +173,34 @@
}
/**
+ * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertSame(Object, Object, String)
+ */
+ public static void assertSame(Object lhs, Object rhs) {
+ assertSame(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is the same as {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertSame(Object lhs, Object rhs, String msg) {
+ if (lhs != rhs) {
+ msg = Objects.toString(msg, "assertSame")
+ + ": expected " + Objects.toString(lhs)
+ + " to equal " + Objects.toString(rhs);
+ throw new RuntimeException(msg);
+ }
+ }
+
+ /**
* Shorthand for {@link #assertGreaterThanOrEqual(T, T)}.
*
* @see #assertGreaterThanOrEqual(T, T)
diff --git a/jdk/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java b/jdk/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java
new file mode 100644
index 0000000..bbed7f4
--- /dev/null
+++ b/jdk/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package com.oracle.testlibrary.jsr292;
+
+import jdk.testlibrary.Asserts;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.*;
+
+public class Helper {
+ /** Flag for verbose output, true if {@code -Dverbose} specified */
+ public static final boolean IS_VERBOSE
+ = System.getProperty("verbose") != null;
+ /**
+ * Flag for thorough testing -- all test will be executed,
+ * true if {@code -Dthorough} specified. */
+ public static final boolean IS_THOROUGH
+ = System.getProperty("thorough") != null;
+ /** Random number generator w/ initial seed equal to {@code -Dseed} */
+ public static final Random RNG;
+
+ static {
+ String str = System.getProperty("seed");
+ long seed = str != null ? Long.parseLong(str) : new Random().nextLong();
+ RNG = new Random(seed);
+ System.out.printf("-Dseed=%d%n", seed);
+ }
+
+ public static final long TEST_LIMIT;
+ static {
+ String str = System.getProperty("testLimit");
+ TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2_000L;
+ System.out.printf("-DtestLimit=%d%n", TEST_LIMIT);
+ }
+
+ public static final int MAX_ARITY = 254;
+ public static final String MISSING_ARG = "missingArg";
+ public static final String MISSING_ARG_2 = "missingArg#2";
+
+ private static final int
+ // first int value
+ ONE_MILLION = (1000 * 1000),
+ // scale factor to reach upper 32 bits
+ TEN_BILLION = (10 * 1000 * 1000 * 1000),
+ // <<1 makes space for sign bit;
+ INITIAL_ARG_VAL = ONE_MILLION << 1;
+
+ public static final MethodHandle AS_LIST;
+
+ static {
+ try {
+ AS_LIST = MethodHandles.lookup().findStatic(
+ Arrays.class, "asList",
+ MethodType.methodType(List.class, Object[].class));
+ } catch (NoSuchMethodException | IllegalAccessException ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isDoubleCost(Class<?> aClass) {
+ return aClass == double.class || aClass == long.class;
+ }
+
+ private static List<List<Object>> calledLog = new ArrayList<>();
+ private static long nextArgVal;
+
+ public static void assertCalled(String name, Object... args) {
+ assertCalled(0, name, args);
+ }
+
+ public static void assertCalled(int lag, String name, Object... args) {
+ Object expected = logEntry(name, args);
+ Object actual = getCalled(lag);
+ Asserts.assertEQ(expected, actual, "method call w/ lag = " + lag);
+ }
+
+ public static Object called(String name, Object... args) {
+ List<Object> entry = logEntry(name, args);
+ calledLog.add(entry);
+ return entry;
+ }
+
+ private static List<Object> logEntry(String name, Object... args) {
+ return Arrays.asList(name, Arrays.asList(args));
+ }
+
+ public static void clear() {
+ calledLog.clear();
+ }
+
+ public static List<Object> getCalled(int lag) {
+ int size = calledLog.size();
+ return size <= lag ? null : calledLog.get(size - lag - 1);
+ }
+
+ public static MethodHandle addTrailingArgs(MethodHandle target, int nargs,
+ List<Class<?>> classes) {
+ int targetLen = target.type().parameterCount();
+ int extra = (nargs - targetLen);
+ if (extra <= 0) {
+ return target;
+ }
+ List<Class<?>> fakeArgs = new ArrayList<>(extra);
+ for (int i = 0; i < extra; ++i) {
+ fakeArgs.add(classes.get(i % classes.size()));
+ }
+ return MethodHandles.dropArguments(target, targetLen, fakeArgs);
+ }
+
+ public static MethodHandle varargsList(int arity) {
+ return AS_LIST.asCollector(Object[].class, arity);
+ }
+
+ private static long nextArg(boolean moreBits) {
+ long val = nextArgVal++;
+ long sign = -(val & 1); // alternate signs
+ val >>= 1;
+ if (moreBits)
+ // Guarantee some bits in the high word.
+ // In any case keep the decimal representation simple-looking,
+ // with lots of zeroes, so as not to make the printed decimal
+ // strings unnecessarily noisy.
+ {
+ val += (val % ONE_MILLION) * TEN_BILLION;
+ }
+ return val ^ sign;
+ }
+
+ private static int nextArg() {
+ // Produce a 32-bit result something like ONE_MILLION+(smallint).
+ // Example: 1_000_042.
+ return (int) nextArg(false);
+ }
+
+ private static long nextArg(Class<?> kind) {
+ if (kind == long.class || kind == Long.class ||
+ kind == double.class || kind == Double.class)
+ // produce a 64-bit result something like
+ // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
+ // Example: 10_000_420_001_000_042.
+ {
+ return nextArg(true);
+ }
+ return (long) nextArg();
+ }
+
+ private static Object randomArg(Class<?> param) {
+ Object wrap = castToWrapperOrNull(nextArg(param), param);
+ if (wrap != null) {
+ return wrap;
+ }
+
+ if (param.isInterface()) {
+ for (Class<?> c : param.getClasses()) {
+ if (param.isAssignableFrom(c) && !c.isInterface()) {
+ param = c;
+ break;
+ }
+ }
+ }
+ if (param.isArray()) {
+ Class<?> ctype = param.getComponentType();
+ Object arg = Array.newInstance(ctype, 2);
+ Array.set(arg, 0, randomArg(ctype));
+ return arg;
+ }
+ if (param.isInterface() && param.isAssignableFrom(List.class)) {
+ return Arrays.asList("#" + nextArg());
+ }
+ if (param.isInterface() || param.isAssignableFrom(String.class)) {
+ return "#" + nextArg();
+ }
+
+ try {
+ return param.newInstance();
+ } catch (InstantiationException | IllegalAccessException ex) {
+ }
+ return null; // random class not Object, String, Integer, etc.
+ }
+
+ public static Object[] randomArgs(Class<?>... params) {
+ Object[] args = new Object[params.length];
+ for (int i = 0; i < args.length; i++) {
+ args[i] = randomArg(params[i]);
+ }
+ return args;
+ }
+
+ public static Object[] randomArgs(int nargs, Class<?> param) {
+ Object[] args = new Object[nargs];
+ for (int i = 0; i < args.length; i++) {
+ args[i] = randomArg(param);
+ }
+ return args;
+ }
+
+ public static Object[] randomArgs(int nargs, Class<?>... params) {
+ Object[] args = new Object[nargs];
+ for (int i = 0; i < args.length; i++) {
+ Class<?> param = params[i % params.length];
+ args[i] = randomArg(param);
+ }
+ return args;
+ }
+
+ public static Object[] randomArgs(List<Class<?>> params) {
+ return randomArgs(params.toArray(new Class<?>[params.size()]));
+ }
+
+ private static Object castToWrapper(Object value, Class<?> dst) {
+ Object wrap = null;
+ if (value instanceof Number) {
+ wrap = castToWrapperOrNull(((Number) value).longValue(), dst);
+ }
+ if (value instanceof Character) {
+ wrap = castToWrapperOrNull((char) (Character) value, dst);
+ }
+ if (wrap != null) {
+ return wrap;
+ }
+ return dst.cast(value);
+ }
+
+ @SuppressWarnings("cast")
+ // primitive cast to (long) is part of the pattern
+ private static Object castToWrapperOrNull(long value, Class<?> dst) {
+ if (dst == int.class || dst == Integer.class) {
+ return (int) (value);
+ }
+ if (dst == long.class || dst == Long.class) {
+ return (long) (value);
+ }
+ if (dst == char.class || dst == Character.class) {
+ return (char) (value);
+ }
+ if (dst == short.class || dst == Short.class) {
+ return (short) (value);
+ }
+ if (dst == float.class || dst == Float.class) {
+ return (float) (value);
+ }
+ if (dst == double.class || dst == Double.class) {
+ return (double) (value);
+ }
+ if (dst == byte.class || dst == Byte.class) {
+ return (byte) (value);
+ }
+ if (dst == boolean.class || dst == boolean.class) {
+ return ((value % 29) & 1) == 0;
+ }
+ return null;
+ }
+}
diff --git a/jdk/test/sun/java2d/DrawXORModeTest.java b/jdk/test/sun/java2d/DrawXORModeTest.java
new file mode 100644
index 0000000..973c9a4
--- /dev/null
+++ b/jdk/test/sun/java2d/DrawXORModeTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014, 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 8036022
+ * @summary Test verifies that drawing shapes with XOR composite
+ * does not trigger an InternalError in GDI surface data.
+ * @run main/othervm -Dsun.java2d.d3d=True DrawXORModeTest
+ */
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Stroke;
+import java.awt.geom.Line2D;
+import java.util.concurrent.CountDownLatch;
+
+public class DrawXORModeTest extends Component {
+
+ public static void main(String[] args) {
+ final DrawXORModeTest c = new DrawXORModeTest();
+
+ final Frame f = new Frame("XOR mode test");
+ f.add(c);
+ f.pack();
+
+ f.setVisible(true);
+
+ try {
+ c.checkResult();
+ } finally {
+ f.dispose();
+ }
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ if (g == null || !(g instanceof Graphics2D)) {
+ return;
+ }
+ g.setColor(Color.white);
+ g.setXORMode(Color.black);
+ Graphics2D dg = (Graphics2D) g;
+ Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_MITER,
+ 10.0f,
+ new float[]{1.0f, 1.0f},
+ 0.0f);
+ dg.setStroke(stroke);
+ try {
+ dg.draw(new Line2D.Float(10, 10, 20, 20));
+ } catch (Throwable e) {
+ synchronized (this) {
+ theError = e;
+ }
+ } finally {
+ didDraw.countDown();
+ }
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(400, 100);
+ }
+
+ public void checkResult() {
+ try {
+ didDraw.await();
+ } catch (InterruptedException e) {
+ }
+
+ synchronized (this) {
+ if (theError != null) {
+ System.out.println("Error: " + theError);
+
+ throw new RuntimeException("Test FAILED.");
+ }
+ }
+ System.out.println("Test PASSED.");
+
+ }
+
+ private Throwable theError = null;
+
+ private final CountDownLatch didDraw = new CountDownLatch(1);
+}
diff --git a/jdk/test/sun/security/krb5/auto/BadKdc.java b/jdk/test/sun/security/krb5/auto/BadKdc.java
index 1c10ccd..d1ace1a 100644
--- a/jdk/test/sun/security/krb5/auto/BadKdc.java
+++ b/jdk/test/sun/security/krb5/auto/BadKdc.java
@@ -39,7 +39,29 @@
// ^ kdc# ^ timeout
static final Pattern re = Pattern.compile(
">>> KDCCommunication: kdc=kdc.rabbit.hole UDP:(\\d)...., " +
- "timeout=(\\d)000,");
+ "timeout=(\\d+),");
+
+ // Ratio for timeout values of all timeout tests. Not final so that
+ // each test can choose their own.
+ static float ratio = 2f;
+
+ static void setRatio(float ratio) {
+ BadKdc.ratio = ratio;
+ }
+
+ static float getRatio() {
+ return ratio;
+ }
+
+ // Gets real timeout value. This method is called when writing krb5.conf
+ static int toReal(int from) {
+ return (int)(from * ratio + .5);
+ }
+
+ // De-ratio a millisecond value to second
+ static int toSymbolicSec(int from) {
+ return (int)(from / ratio / 1000f + 0.5);
+ }
/*
* There are several cases this test fails:
@@ -101,7 +123,7 @@
fw.write("[libdefaults]\n" +
"default_realm = " + OneKDC.REALM + "\n" +
- "kdc_timeout = 2000\n");
+ "kdc_timeout = " + toReal(2000) + "\n");
fw.write("[realms]\n" + OneKDC.REALM + " = {\n" +
"kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" +
"kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" +
@@ -184,7 +206,8 @@
Matcher m = re.matcher(line);
if (m.find()) {
System.out.println(line);
- sb.append(m.group(1)).append(m.group(2));
+ sb.append(m.group(1))
+ .append(toSymbolicSec(Integer.parseInt(m.group(2))));
}
}
if (failed) sb.append('-');
diff --git a/jdk/test/sun/security/krb5/auto/BadKdc1.java b/jdk/test/sun/security/krb5/auto/BadKdc1.java
index 7db7b8a..dd60893 100644
--- a/jdk/test/sun/security/krb5/auto/BadKdc1.java
+++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java
@@ -28,14 +28,21 @@
* @summary krb5 should not try to access unavailable kdc too often
*/
-import java.io.*;
import java.security.Security;
public class BadKdc1 {
public static void main(String[] args)
throws Exception {
- Security.setProperty("krb5.kdc.bad.policy", "tryLess");
+
+ // 5 sec is default timeout for tryLess
+ if (BadKdc.getRatio() > 2.5) {
+ Security.setProperty("krb5.kdc.bad.policy",
+ "tryLess:1," + BadKdc.toReal(2000));
+ } else {
+ Security.setProperty("krb5.kdc.bad.policy", "tryLess");
+ }
+
BadKdc.go(
"121212222222(32){1,2}1222(32){1,2}", // 1 2
// The above line means try kdc1 for 2 seconds then kdc1
diff --git a/jdk/test/sun/security/krb5/auto/BadKdc2.java b/jdk/test/sun/security/krb5/auto/BadKdc2.java
index 7568784..4291d5c 100644
--- a/jdk/test/sun/security/krb5/auto/BadKdc2.java
+++ b/jdk/test/sun/security/krb5/auto/BadKdc2.java
@@ -35,7 +35,12 @@
public static void main(String[] args)
throws Exception {
- Security.setProperty("krb5.kdc.bad.policy", "tryLess:2,1000");
+
+ // 1 sec is too short.
+ BadKdc.setRatio(3.0f);
+
+ Security.setProperty(
+ "krb5.kdc.bad.policy", "tryLess:2," + BadKdc.toReal(1000));
BadKdc.go(
"121212222222(32){1,2}11112121(32){1,2}", // 1 2
"11112121(32){1,2}11112121(32){1,2}", // 1 2
diff --git a/jdk/test/sun/security/krb5/auto/MaxRetries.java b/jdk/test/sun/security/krb5/auto/MaxRetries.java
index 2e896bc..880c023 100644
--- a/jdk/test/sun/security/krb5/auto/MaxRetries.java
+++ b/jdk/test/sun/security/krb5/auto/MaxRetries.java
@@ -60,7 +60,7 @@
test1(5000, 2); // 2 2
// For tryLess
- Security.setProperty("krb5.kdc.bad.policy", "tryless");
+ Security.setProperty("krb5.kdc.bad.policy", "tryless:1," + BadKdc.toReal(5000));
rewriteMaxRetries(4);
test1(4000, 7); // 1 1 1 1 2 1 2
test1(4000, 4); // 1 2 1 2
@@ -94,7 +94,7 @@
* @param count the expected total try
*/
private static void test1(int timeout, int count) throws Exception {
- String timeoutTag = "timeout=" + timeout;
+ String timeoutTag = "timeout=" + BadKdc.toReal(timeout);
ByteArrayOutputStream bo = new ByteArrayOutputStream();
PrintStream oldout = System.out;
System.setOut(new PrintStream(bo));
@@ -192,12 +192,12 @@
if (s.startsWith("[realms]")) {
// Reconfig global setting
fw.write("max_retries = 2\n");
- fw.write("kdc_timeout = 5000\n");
+ fw.write("kdc_timeout = " + BadKdc.toReal(5000) + "\n");
} else if (s.trim().startsWith("kdc = ")) {
if (value != -1) {
// Reconfig for realm
fw.write(" max_retries = " + value + "\n");
- fw.write(" kdc_timeout = " + (value*1000) + "\n");
+ fw.write(" kdc_timeout = " + BadKdc.toReal(value*1000) + "\n");
}
// Add a bad KDC as the first candidate
fw.write(" kdc = localhost:33333\n");
diff --git a/jdk/test/sun/security/krb5/auto/TcpTimeout.java b/jdk/test/sun/security/krb5/auto/TcpTimeout.java
index 325d5bb..45699fb 100644
--- a/jdk/test/sun/security/krb5/auto/TcpTimeout.java
+++ b/jdk/test/sun/security/krb5/auto/TcpTimeout.java
@@ -63,7 +63,7 @@
"udp_preference_limit = 1\n" +
"max_retries = 2\n" +
"default_realm = " + OneKDC.REALM + "\n" +
- "kdc_timeout = 5000\n");
+ "kdc_timeout = " + BadKdc.toReal(5000) + "\n");
fw.write("[realms]\n" + OneKDC.REALM + " = {\n" +
"kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" +
"kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" +
diff --git a/jdk/test/sun/security/krb5/config/ExtraLines.java b/jdk/test/sun/security/krb5/config/ExtraLines.java
new file mode 100644
index 0000000..babb0c0
--- /dev/null
+++ b/jdk/test/sun/security/krb5/config/ExtraLines.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 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 8036971
+ * @compile -XDignore.symbol.file ExtraLines.java
+ * @run main/othervm ExtraLines
+ * @summary krb5.conf does not accept directive lines before the first section
+ */
+
+import sun.security.krb5.Config;
+import java.nio.file.*;
+import java.util.Objects;
+
+public class ExtraLines {
+ public static void main(String[] args) throws Exception {
+ Path base = Paths.get("krb5.conf");
+ Path include = Paths.get("included.conf");
+ String baseConf = "include " + include.toAbsolutePath().toString()
+ + "\n[x]\na = b\n";
+ String includeConf = "[y]\nc = d\n";
+ Files.write(include, includeConf.getBytes());
+ Files.write(base, baseConf.getBytes());
+
+ System.setProperty("java.security.krb5.conf", base.toString());
+ Config.refresh();
+
+ if (!Objects.equals(Config.getInstance().get("x", "a"), "b")) {
+ throw new Exception("Failed");
+ }
+ }
+}
diff --git a/jdk/test/sun/security/provider/certpath/PKIXCertPathValidator/Validity.java b/jdk/test/sun/security/provider/certpath/PKIXCertPathValidator/Validity.java
new file mode 100644
index 0000000..056a369
--- /dev/null
+++ b/jdk/test/sun/security/provider/certpath/PKIXCertPathValidator/Validity.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2014, 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 8021804
+ * @summary CertPath should validate even if the validity period of the
+ * root cert does not include the validity period of a subordinate
+ * cert.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+public class Validity {
+
+ /*
+ * Subject: OU=TestOrg, CN=TestCA
+ * Issuer: OU=TestOrg, CN=TestCA
+ * Validity
+ * Not Before: Feb 26 21:33:55 2014 GMT
+ Not After : Feb 26 21:33:55 2024 GMT
+ * Version 1
+ */
+ static String CACertStr =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBvTCCASYCCQCQRiTo4lBCFjANBgkqhkiG9w0BAQUFADAjMRAwDgYDVQQLDAdU\n" +
+ "ZXN0T3JnMQ8wDQYDVQQDDAZUZXN0Q0EwHhcNMTQwMjI2MjEzMzU1WhcNMjQwMjI2\n" +
+ "MjEzMzU1WjAjMRAwDgYDVQQLDAdUZXN0T3JnMQ8wDQYDVQQDDAZUZXN0Q0EwgZ8w\n" +
+ "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOtKS4ZrsM3ansd61ZxitcrN0w184I+A\n" +
+ "z0kyrSP1eMtlam+cC2U91NpTz11FYV4XUfBhqqxaXW043AWTUer8pS90Pt4sCrUX\n" +
+ "COx1+QA1M3ZhbZ4sTM7XQ90JbGaBJ/sEza9mlQP7hQ2yQO/hATKbP6J5qvgG2sT2\n" +
+ "S2WYjEgwNwmFAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQ/CXEpnx2WY4LJtv4jwE\n" +
+ "4jIVirur3pdzV5oBhPyqqHMsyhQBkukCfX7uD7L5wN1+xuM81DfANpIxlnUfybp5\n" +
+ "CpjcmktLpmyK4kJ6XnSd2blbLOIpsr9x6FqxPxpVDlyw/ySHYrIG/GZdsLHgmzGn\n" +
+ "B06jeYzH8OLf879VxAxSsPc=\n" +
+ "-----END CERTIFICATE-----";
+
+ /*
+ * Subject: OU=TestOrg, CN=TestEE0
+ * Issuer: OU=TestOrg, CN=TestCA
+ * Validity
+ * Not Before: Feb 26 22:55:12 2014 GMT
+ * Not After : Feb 25 22:55:12 2025 GMT
+ * Version 1
+ */
+ static String EECertStr =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBtjCCAR8CAQQwDQYJKoZIhvcNAQEFBQAwIzEQMA4GA1UECwwHVGVzdE9yZzEP\n" +
+ "MA0GA1UEAwwGVGVzdENBMB4XDTE0MDIyNjIyNTUxMloXDTI1MDIyNTIyNTUxMlow\n" +
+ "JDEQMA4GA1UECwwHVGVzdE9yZzEQMA4GA1UEAwwHVGVzdEVFMDCBnzANBgkqhkiG\n" +
+ "9w0BAQEFAAOBjQAwgYkCgYEAt8xz9W3ruCTHjSOtTX6cxsUZ0nRP6EavEfzgcOYh\n" +
+ "CXGA0gr+viSHq3c2vQBxiRny2hm5rLcqpPo+2OxZtw/ajxfyrV6d/r8YyQLBvyl3\n" +
+ "xdCZdOkG1DCM1oFAQDaSRt9wN5Zm5kyg7uMig5Y4L45fP9Yee4x6Xyh36qYbsR89\n" +
+ "rFMCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDZrPqSo08va1m9TOWOztTuWilGdjK/\n" +
+ "2Ed2WXg8utIpy6uAV+NaOYtHQ7ULQBVRNmwg9nKghbVbh+E/xpoihjl1x7OXass4\n" +
+ "TbwXA5GKFIFpNtDvATQ/QQZoCuCzw1FW/mH0Q7UEQ/9/iJdDad6ebkapeMwtj/8B\n" +
+ "s2IZV7s85CEOXw==\n" +
+ "-----END CERTIFICATE-----";
+
+ public static void main(String[] args) throws Exception {
+
+ String[] certStrs = {EECertStr};
+ String[] trustedCertStrs = {CACertStr};
+ runTest(certStrs, trustedCertStrs);
+
+ System.out.println("Test passed.");
+ }
+
+ private static void runTest(String[] certStrs,
+ String[] trustedCertStrs)
+ throws Exception {
+
+ CertificateFactory cf = CertificateFactory.getInstance("X509");
+
+ // Generate the CertPath from the certs named in certStrs
+ ArrayList<X509Certificate> certs = new ArrayList<>();
+ for (String certStr : certStrs) {
+ certs.add(generateCert(certStr, cf));
+ }
+ CertPath cp = cf.generateCertPath(certs);
+
+ // Generate the set of Trust Anchors from the certs named in
+ // trustedCertStrs
+ Set<TrustAnchor> trustAnchors = new HashSet<>();
+ for (String trustedCertStr : trustedCertStrs) {
+ TrustAnchor ta = new TrustAnchor(generateCert(trustedCertStr, cf),
+ null);
+ trustAnchors.add(ta);
+ }
+ PKIXParameters params = new PKIXParameters(trustAnchors);
+ params.setDate(new Date(114, 3, 1)); // 2014-03-01
+ params.setRevocationEnabled(false);
+
+ // Attempt to validate the CertPath. If no exception thrown, successful.
+ CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+ cpv.validate(cp, params);
+ System.out.println("CertPath validation successful.");
+ }
+
+ private static X509Certificate generateCert(String certStr,
+ CertificateFactory cf)
+ throws Exception {
+ ByteArrayInputStream stream
+ = new ByteArrayInputStream(certStr.getBytes());
+ return (X509Certificate) cf.generateCertificate(stream);
+
+ }
+}
diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData
index afd66e14..c015be5 100644
--- a/jdk/test/sun/text/resources/LocaleData
+++ b/jdk/test/sun/text/resources/LocaleData
@@ -431,10 +431,6 @@
FormatData/es_CL/NumberPatterns/0=#,##0.###;-#,##0.###
# FormatData/es_CL/NumberPatterns/1=Ch$#,##0.00;Ch$-#,##0.00 # Changed; see bug 4122840
FormatData/es_CL/NumberPatterns/2=#,##0%
-FormatData/es_CL/TimePatterns/0=hh:mm:ss a z
-FormatData/es_CL/TimePatterns/1=hh:mm:ss a z
-FormatData/es_CL/TimePatterns/2=hh:mm:ss a
-FormatData/es_CL/TimePatterns/3=hh:mm a
FormatData/es_CL/DatePatterns/0=EEEE d' de 'MMMM' de 'yyyy
FormatData/es_CL/DatePatterns/1=d' de 'MMMM' de 'yyyy
FormatData/es_CL/DatePatterns/2=dd-MM-yyyy
@@ -498,10 +494,6 @@
FormatData/es_EC/NumberPatterns/2=#,##0%
#changed for 4945388
CurrencyNames/es_EC/USD=$
-FormatData/es_EC/TimePatterns/0=hh:mm:ss a z
-FormatData/es_EC/TimePatterns/1=hh:mm:ss a z
-FormatData/es_EC/TimePatterns/2=hh:mm:ss a
-FormatData/es_EC/TimePatterns/3=hh:mm a
FormatData/es_EC/DatePatterns/0=EEEE d' de 'MMMM' de 'yyyy
FormatData/es_EC/DatePatterns/1=d' de 'MMMM' de 'yyyy
FormatData/es_EC/DatePatterns/2=dd/MM/yyyy
@@ -7693,3 +7685,13 @@
# bug 8027695
FormatData/sv_SE/NumberPatterns/2=#,##0 %
+
+# bug 8017142
+FormatData/es_CL/TimePatterns/0=HH:mm:ss zzzz
+FormatData/es_CL/TimePatterns/1=H:mm:ss z
+FormatData/es_CL/TimePatterns/2=H:mm:ss
+FormatData/es_CL/TimePatterns/3=H:mm
+FormatData/es_EC/TimePatterns/0=HH:mm:ss zzzz
+FormatData/es_EC/TimePatterns/1=H:mm:ss z
+FormatData/es_EC/TimePatterns/2=H:mm:ss
+FormatData/es_EC/TimePatterns/3=H:mm
diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java
index 1c9aa5b..7381bb6 100644
--- a/jdk/test/sun/text/resources/LocaleDataTest.java
+++ b/jdk/test/sun/text/resources/LocaleDataTest.java
@@ -36,6 +36,7 @@
* 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
* 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
* 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 7090826
+ * 8017142
* @summary Verify locale data
*
*/
diff --git a/langtools/.hgtags b/langtools/.hgtags
index 6712a3e..768d7af 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -262,3 +262,4 @@
c8a87a58eb3efdd64055566b502c9d4a72ca0996 jdk8-b132
c6d0108aca9f8f45b9cddeb6e483d464509e0127 jdk8u20-b06
1a57c569cb811a897691e42049eca33da8f8d761 jdk8u20-b07
+0f821eb7e92b242c878dca68ef63f9626643ee8f jdk8u20-b08
diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java
index cb3637c..740942d 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -467,11 +467,24 @@
private boolean hiddenIn(ClassSymbol clazz, Types types) {
Symbol sym = hiddenInInternal(clazz, types);
- return sym != null && sym != this;
+ Assert.check(sym != null, "the result of hiddenInInternal() can't be null");
+ /* If we find the current symbol then there is no symbol hiding it
+ */
+ return sym != this;
}
- private Symbol hiddenInInternal(ClassSymbol c, Types types) {
- Scope.Entry e = c.members().lookup(name);
+ /** This method looks in the supertypes graph that has the current class as the
+ * initial node, till it finds the current symbol or another symbol that hides it.
+ * If the current class has more than one supertype (extends one class and
+ * implements one or more interfaces) then null can be returned, meaning that
+ * a wrong path in the supertypes graph was selected. Null can only be returned
+ * as a temporary value, as a result of the recursive call.
+ */
+ private Symbol hiddenInInternal(ClassSymbol currentClass, Types types) {
+ if (currentClass == owner) {
+ return this;
+ }
+ Scope.Entry e = currentClass.members().lookup(name);
while (e.scope != null) {
if (e.sym.kind == kind &&
(kind != MTH ||
@@ -481,18 +494,19 @@
}
e = e.next();
}
- List<Symbol> hiddenSyms = List.nil();
- for (Type st : types.interfaces(c.type).prepend(types.supertype(c.type))) {
+ Symbol hiddenSym = null;
+ for (Type st : types.interfaces(currentClass.type)
+ .prepend(types.supertype(currentClass.type))) {
if (st != null && (st.hasTag(CLASS))) {
Symbol sym = hiddenInInternal((ClassSymbol)st.tsym, types);
- if (sym != null) {
- hiddenSyms = hiddenSyms.prepend(hiddenInInternal((ClassSymbol)st.tsym, types));
+ if (sym == this) {
+ return this;
+ } else if (sym != null) {
+ hiddenSym = sym;
}
}
}
- return hiddenSyms.contains(this) ?
- this :
- (hiddenSyms.isEmpty() ? null : hiddenSyms.head);
+ return hiddenSym;
}
/** Is this symbol inherited into a given class?
diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java
index bcf0c83..68ab8db 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -1481,8 +1481,21 @@
}
public String toString() {
- if (inst != null) return inst.toString();
- else return qtype + "?";
+ return (inst == null) ? qtype + "?" : inst.toString();
+ }
+
+ public String debugString() {
+ String result = "inference var = " + qtype + "\n";
+ if (inst != null) {
+ result += "inst = " + inst + '\n';
+ }
+ for (InferenceBound bound: InferenceBound.values()) {
+ List<Type> aboundList = bounds.get(bound);
+ if (aboundList.size() > 0) {
+ result += bound + " = " + aboundList + '\n';
+ }
+ }
+ return result;
}
@Override
@@ -1492,8 +1505,7 @@
@Override
public Type baseType() {
- if (inst != null) return inst.baseType();
- else return this;
+ return (inst == null) ? this : inst.baseType();
}
/** get all bounds of a given kind */
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
index 2fe9474..6943011 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -2119,6 +2119,12 @@
//back-door to infer
return Infer.this;
}
+
+ @Override
+ public String toString() {
+ return "Inference vars: " + inferencevars + '\n' +
+ "Undet vars: " + undetvars;
+ }
}
final InferenceContext emptyContext = new InferenceContext(List.<Type>nil());
diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
index fbee06b..83d43af 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
@@ -1038,7 +1038,7 @@
}
databuf.appendChar(pool.get(inner));
databuf.appendChar(
- inner.owner.kind == TYP ? pool.get(inner.owner) : 0);
+ inner.owner.kind == TYP && !inner.name.isEmpty() ? pool.get(inner.owner) : 0);
databuf.appendChar(
!inner.name.isEmpty() ? pool.get(inner.name) : 0);
databuf.appendChar(flags);
diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java
index 69f2bea..1ed2fbb 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -2189,9 +2189,9 @@
// Keep local variables if
// 1) we need them for debug information
// 2) it is an exception type and it contains type annotations
- if (!varDebugInfo &&
- (!var.sym.isExceptionParameter() ||
- var.sym.hasTypeAnnotations())) return;
+ boolean keepLocalVariables = varDebugInfo ||
+ (var.sym.isExceptionParameter() && var.sym.hasTypeAnnotations());
+ if (!keepLocalVariables) return;
if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
if (varBuffer == null)
varBuffer = new LocalVar[20];
diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
index 95816d2..54942c4 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
@@ -762,14 +762,14 @@
public Set<TypeElement> visitType(TypeElement e, Set<TypeElement> p) {
// Type parameters are not considered to be enclosed by a type
scan(e.getTypeParameters(), p);
- return scan(e.getEnclosedElements(), p);
+ return super.visitType(e, p);
}
@Override
public Set<TypeElement> visitExecutable(ExecutableElement e, Set<TypeElement> p) {
// Type parameters are not considered to be enclosed by an executable
scan(e.getTypeParameters(), p);
- return scan(e.getEnclosedElements(), p);
+ return super.visitExecutable(e, p);
}
void addAnnotations(Element e, Set<TypeElement> p) {
diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java
index 3853ac0..78b9453 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java
@@ -137,14 +137,14 @@
public Set<Element> visitType(TypeElement e, TypeElement p) {
// Type parameters are not considered to be enclosed by a type
scan(e.getTypeParameters(), p);
- return scan(e.getEnclosedElements(), p);
+ return super.visitType(e, p);
}
@Override
public Set<Element> visitExecutable(ExecutableElement e, TypeElement p) {
// Type parameters are not considered to be enclosed by an executable
scan(e.getTypeParameters(), p);
- return scan(e.getEnclosedElements(), p);
+ return super.visitExecutable(e, p);
}
@Override
diff --git a/langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java
index 83b8ba8..a483775 100644
--- a/langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java
+++ b/langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java
@@ -202,7 +202,6 @@
if (options.verbose) {
println();
indent(+1);
- attrWriter.write(cf, cf.attributes, constant_pool);
println("minor version: " + cf.minor_version);
println("major version: " + cf.major_version);
writeList("flags: ", flags.getClassFlags(), "\n");
@@ -218,6 +217,10 @@
writeMethods();
indent(-1);
println("}");
+
+ if (options.verbose) {
+ attrWriter.write(cf, cf.attributes, constant_pool);
+ }
}
// where
class JavaTypePrinter implements Type.Visitor<StringBuilder,StringBuilder> {
diff --git a/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java b/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java
new file mode 100644
index 0000000..a447d22
--- /dev/null
+++ b/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, 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 8034924
+ * @summary Incorrect inheritance of inaccessible static method
+ * @library /tools/javac/lib
+ * @build ToolBox
+ * @run main IncorrectInheritanceTest
+ */
+
+public class IncorrectInheritanceTest {
+ private static final String ASrc =
+ "package pkg;\n" +
+ "\n" +
+ "public class A {\n" +
+ " static void foo(Object o) {}\n" +
+ " private static void bar(Object o) {}\n" +
+ "}";
+
+ private static final String BSrc =
+ "import pkg.A;\n" +
+ "class B extends A {\n" +
+ " public void foo(Object o) {}\n" +
+ " public void bar(Object o) {}\n" +
+ "}";
+
+ private static final String CSrc =
+ "class C extends B {\n" +
+ " public void m(Object o) {\n" +
+ " foo(o);\n" +
+ " bar(o);\n" +
+ " }\n" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ new IncorrectInheritanceTest().test();
+ }
+
+ public void test() throws Exception {
+ ToolBox.JavaToolArgs javacParams =
+ new ToolBox.JavaToolArgs()
+ .setSources(ASrc, BSrc, CSrc);
+ ToolBox.javac(javacParams);
+ }
+
+}
diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java
index feaa4f3..cb1ceaf 100644
--- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -30,6 +30,7 @@
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -51,6 +52,11 @@
new Driver().runDriver(clazz.newInstance());
}
+ String[][] extraParamsCombinations = new String[][] {
+ new String[] { },
+ new String[] { "-g" },
+ };
+
protected void runDriver(Object object) throws Exception {
int passed = 0, failed = 0;
Class<?> clazz = object.getClass();
@@ -65,18 +71,20 @@
throw new IllegalArgumentException("Test method needs to return a string: " + method);
String testClass = testClassOf(method);
- try {
- String compact = (String)method.invoke(object);
- String fullFile = wrap(compact);
- ClassFile cf = compileAndReturn(fullFile, testClass);
- List<TypeAnnotation> actual = ReferenceInfoUtil.extendedAnnotationsOf(cf);
- ReferenceInfoUtil.compare(expected, actual, cf);
- out.println("PASSED: " + method.getName());
- ++passed;
- } catch (Throwable e) {
- out.println("FAILED: " + method.getName());
- out.println(" " + e.toString());
- ++failed;
+ for (String[] extraParams : extraParamsCombinations) {
+ try {
+ String compact = (String)method.invoke(object);
+ String fullFile = wrap(compact);
+ ClassFile cf = compileAndReturn(fullFile, testClass, extraParams);
+ List<TypeAnnotation> actual = ReferenceInfoUtil.extendedAnnotationsOf(cf);
+ ReferenceInfoUtil.compare(expected, actual, cf);
+ out.println("PASSED: " + method.getName());
+ ++passed;
+ } catch (Throwable e) {
+ out.println("FAILED: " + method.getName());
+ out.println(" " + e.toString());
+ ++failed;
+ }
}
}
@@ -156,7 +164,7 @@
}
}
- private ClassFile compileAndReturn(String fullFile, String testClass) throws Exception {
+ private ClassFile compileAndReturn(String fullFile, String testClass, String... extraParams) throws Exception {
File source = writeTestFile(fullFile);
File clazzFile = compileTestFile(source, testClass);
return ClassFile.read(clazzFile);
@@ -170,8 +178,12 @@
return f;
}
- protected File compileTestFile(File f, String testClass) {
- int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() });
+ protected File compileTestFile(File f, String testClass, String... extraParams) {
+ List<String> options = new ArrayList<>();
+ options.addAll(Arrays.asList("-source", "1.8"));
+ options.addAll(Arrays.asList(extraParams));
+ options.add(f.getPath());
+ int rc = com.sun.tools.javac.Main.compile(options.toArray(new String[options.size()]));
if (rc != 0)
throw new Error("compilation failed. rc=" + rc);
String path;
diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java
index 790a514..f41cff9 100644
--- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,6 +25,7 @@
/*
* @test
+ * @bug 8028576
* @summary Test population of reference info for exception parameters
* @author Werner Dietl
* @compile -g Driver.java ReferenceInfoUtil.java ExceptionParameters.java
diff --git a/langtools/test/tools/javac/classfiles/InnerClasses/SyntheticClasses.java b/langtools/test/tools/javac/classfiles/InnerClasses/SyntheticClasses.java
new file mode 100644
index 0000000..58a8f9a
--- /dev/null
+++ b/langtools/test/tools/javac/classfiles/InnerClasses/SyntheticClasses.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 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 8034854
+ * @summary Verify that the InnerClasses attribute has outer_class_info_index zero if it has
+ * inner_name_index zero (for synthetic classes)
+ * @compile SyntheticClasses.java
+ * @run main SyntheticClasses
+ */
+
+import java.io.*;
+import java.util.*;
+import com.sun.tools.classfile.*;
+
+public class SyntheticClasses {
+
+ public static void main(String[] args) throws IOException, ConstantPoolException {
+ new SyntheticClasses().run();
+ }
+
+ private void run() throws IOException, ConstantPoolException {
+ File testClasses = new File(System.getProperty("test.classes"));
+ for (File classFile : testClasses.listFiles()) {
+ ClassFile cf = ClassFile.read(classFile);
+ if (cf.getName().matches(".*\\$[0-9]+")) {
+ EnclosingMethod_attribute encl =
+ (EnclosingMethod_attribute) cf.getAttribute(Attribute.EnclosingMethod);
+ if (encl != null) {
+ if (encl.method_index != 0)
+ throw new IllegalStateException("Invalid EnclosingMethod.method_index: " +
+ encl.method_index + ".");
+ }
+ }
+ InnerClasses_attribute attr =
+ (InnerClasses_attribute) cf.getAttribute(Attribute.InnerClasses);
+ if (attr != null) {
+ for (InnerClasses_attribute.Info info : attr.classes) {
+ if (cf.major_version < 51)
+ throw new IllegalStateException();
+ if (info.inner_name_index == 0 && info.outer_class_info_index != 0)
+ throw new IllegalStateException("Invalid outer_class_info_index=" +
+ info.outer_class_info_index +
+ "; inner_name_index=" +
+ info.inner_name_index + ".");
+ }
+ }
+ }
+ }
+}
+
+class SyntheticConstructorAccessTag {
+
+ private static class A {
+ private A(){}
+ }
+
+ public void test() {
+ new A();
+ }
+}
+
+class SyntheticEnumMapping {
+ private int convert(E e) {
+ switch (e) {
+ case A: return 0;
+ default: return -1;
+ }
+ }
+ enum E { A }
+}
+
+interface SyntheticAssertionsDisabled {
+ public default void test() {
+ assert false;
+ }
+}
diff --git a/langtools/test/tools/javac/processing/environment/ProcessingEnvAnnoDiscovery.java b/langtools/test/tools/javac/processing/environment/ProcessingEnvAnnoDiscovery.java
new file mode 100644
index 0000000..ef2721f
--- /dev/null
+++ b/langtools/test/tools/javac/processing/environment/ProcessingEnvAnnoDiscovery.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 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 8038080
+ * @summary make sure that all declaration annotations are discovered
+ * by the processing environment
+ * @library /tools/javac/lib
+ * @build JavacTestingAbstractProcessor ProcessingEnvAnnoDiscovery
+ * @compile/process -processor ProcessingEnvAnnoDiscovery ProcessingEnvAnnoDiscovery.java
+ */
+
+import java.lang.annotation.*;
+import java.util.Set;
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+import com.sun.tools.javac.util.*;
+
+@ProcessingEnvAnnoDiscovery.Anno1
+public class ProcessingEnvAnnoDiscovery<@ProcessingEnvAnnoDiscovery.Anno4 T>
+ extends JavacTestingAbstractProcessor {
+ private int round = 0;
+
+ public boolean process(Set<? extends TypeElement> annos, RoundEnvironment rEnv) {
+ if (round++ == 0) {
+ System.out.println(annos);
+ Assert.check(annos.contains(eltUtils.getTypeElement("java.lang.annotation.Target")));
+ Assert.check(annos.contains(eltUtils.getTypeElement("ProcessingEnvAnnoDiscovery.Anno1")));
+ Assert.check(annos.contains(eltUtils.getTypeElement("ProcessingEnvAnnoDiscovery.Anno2")));
+ Assert.check(annos.contains(eltUtils.getTypeElement("ProcessingEnvAnnoDiscovery.Anno3")));
+ Assert.check(annos.contains(eltUtils.getTypeElement("ProcessingEnvAnnoDiscovery.Anno4")));
+ Assert.check(annos.contains(eltUtils.getTypeElement("ProcessingEnvAnnoDiscovery.Anno5")));
+ Assert.check(annos.size() == 6, "Found extra annotations"); //Anno1-5 + @Target
+ }
+
+ return true;
+ }
+
+ @Anno2
+ public <@Anno5 K> K m(@Anno3 long foo) {
+ return null;
+ }
+
+ @interface Anno1 {}
+
+ @interface Anno2 {}
+
+ @interface Anno3 {}
+
+ @Target(ElementType.TYPE_PARAMETER)
+ @interface Anno4 {}
+
+ @Target(ElementType.TYPE_PARAMETER)
+ @interface Anno5 {}
+
+}
diff --git a/langtools/test/tools/javac/processing/environment/round/Anno.java b/langtools/test/tools/javac/processing/environment/round/Anno.java
new file mode 100644
index 0000000..366b489
--- /dev/null
+++ b/langtools/test/tools/javac/processing/environment/round/Anno.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, 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.lang.annotation.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+@Retention(RUNTIME)
+public @interface Anno {}
diff --git a/langtools/test/tools/javac/processing/environment/round/ParameterAnnotations.java b/langtools/test/tools/javac/processing/environment/round/ParameterAnnotations.java
new file mode 100644
index 0000000..a4433e3
--- /dev/null
+++ b/langtools/test/tools/javac/processing/environment/round/ParameterAnnotations.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * Class to hold annotations for ElementsAnnotatedWithTest.
+ */
+
+@AnnotatedElementInfo(annotationName="Anno",
+ expectedSize=1,
+ names={"annotatedParameter"})
+public class ParameterAnnotations {
+ private void foo(@Anno Object annotatedParameter) {}
+}
diff --git a/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java b/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java
index 3a02006..398b2f5 100644
--- a/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java
+++ b/langtools/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938 6911854 8030049
+ * @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938 6911854 8030049 8038080
* @summary Tests that getElementsAnnotatedWith works properly.
* @author Joseph D. Darcy
* @library /tools/javac/lib
@@ -31,12 +31,14 @@
* @compile TestElementsAnnotatedWith.java
* @compile InheritedAnnotation.java
* @compile TpAnno.java
+ * @compile Anno.java
* @compile -processor TestElementsAnnotatedWith -proc:only SurfaceAnnotations.java
* @compile -processor TestElementsAnnotatedWith -proc:only BuriedAnnotations.java
* @compile -processor TestElementsAnnotatedWith -proc:only Part1.java Part2.java
* @compile -processor TestElementsAnnotatedWith -proc:only C2.java
* @compile -processor TestElementsAnnotatedWith -proc:only Foo.java
* @compile -processor TestElementsAnnotatedWith -proc:only TypeParameterAnnotations.java
+ * @compile -processor TestElementsAnnotatedWith -proc:only ParameterAnnotations.java
* @compile/fail/ref=ErroneousAnnotations.out -processor TestElementsAnnotatedWith -proc:only -XDrawDiagnostics ErroneousAnnotations.java
* @compile Foo.java
* @compile/process -processor TestElementsAnnotatedWith -proc:only Foo
diff --git a/langtools/test/tools/javap/T4975569.java b/langtools/test/tools/javap/T4975569.java
index b4a5549..faf45f0 100644
--- a/langtools/test/tools/javap/T4975569.java
+++ b/langtools/test/tools/javap/T4975569.java
@@ -40,10 +40,10 @@
verify("T4975569$Anno", "flags: ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION");
verify("T4975569$E", "flags: ACC_FINAL, ACC_SUPER, ACC_ENUM");
verify("T4975569$S", "flags: ACC_BRIDGE, ACC_SYNTHETIC",
- "InnerClasses:\n static");
+ "InnerClasses:\n static");
verify("T4975569$V", "void m(java.lang.String...)",
"flags: ACC_VARARGS");
- verify("T4975569$Prot", "InnerClasses:\n protected");
+ verify("T4975569$Prot", "InnerClasses:\n protected");
//verify("T4975569$Priv", "InnerClasses");
if (errors > 0)
throw new Error(errors + " found.");
diff --git a/langtools/test/tools/javap/T8035104.java b/langtools/test/tools/javap/T8035104.java
new file mode 100644
index 0000000..37ef8fc
--- /dev/null
+++ b/langtools/test/tools/javap/T8035104.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 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 8035104
+ * @summary reorder class file attributes in javap listing
+ */
+
+import java.io.*;
+
+public class T8035104 {
+ public static void main(String[] args) throws Exception {
+ new T8035104().run();
+ }
+
+ public void run() throws Exception {
+ String[] lines = javap("-v", T8035104.class.getName()).split("[\r\n]+");
+ int minor = -1;
+ int SourceFile = -1;
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ if (line.matches(" *minor version: [0-9.]+"))
+ minor = i;
+ if (line.matches(" *SourceFile: .+"))
+ SourceFile = i;
+ }
+ if (minor == -1)
+ throw new Exception("minor version not found");
+ if (SourceFile == -1)
+ throw new Exception("SourceFile not found");
+ if (SourceFile < minor)
+ throw new Exception("unexpected order of output");
+
+ System.out.println("output OK");
+ }
+
+ String javap(String... args) {
+ StringWriter sw = new StringWriter();
+ PrintWriter out = new PrintWriter(sw);
+ int rc = com.sun.tools.javap.Main.run(args, out);
+ out.close();
+ System.out.println(sw.toString());
+ System.out.println("javap exited, rc=" + rc);
+ return sw.toString();
+ }
+}
diff --git a/make/Jprt.gmk b/make/Jprt.gmk
index 0075adc..c40e852 100644
--- a/make/Jprt.gmk
+++ b/make/Jprt.gmk
@@ -106,6 +106,9 @@
ifdef ENABLE_SJAVAC
@$(ECHO) " --enable-sjavac" >> $@.tmp
endif
+ ifdef JDK_UPDATE_VERSION
+ @$(ECHO) " --with-update-version=$(JDK_UPDATE_VERSION)" >> $@.tmp
+ endif
ifeq ($(HOTSPOT_AVAILABLE),false)
ifdef ALT_JDK_IMPORT_PATH
@$(ECHO) " --with-import-hotspot=$(call UnixPath,$(ALT_JDK_IMPORT_PATH)) " >> $@.tmp
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index d58b95f..fe6e8e4 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -250,3 +250,4 @@
5dbdae28a6f3dae3913b118c128bcb1f803317ac jdk8-b132
4268cd11c2411064ac30dee7a668055ce226c268 jdk8u20-b06
7e89db817ed094766a039762a8061c3a600c7284 jdk8u20-b07
+2282c86cb1a954efd2fc5b7f22c173be19087c55 jdk8u20-b08
diff --git a/nashorn/README b/nashorn/README
index 52b3091..242d607 100644
--- a/nashorn/README
+++ b/nashorn/README
@@ -81,13 +81,13 @@
After that, you can run the tests using:
cd make
- ant test
+ ant clean test
You can also run the ECMA-262 test suite with Nashorn. In order to do
that, you will need to get a copy of it and put it in
test/script/external/test262 directory. A convenient way to do it is:
- hg clone http://hg.ecmascript.org/tests/test262/ test/script/external/test262
+ git clone https://github.com/tc39/test262 test/script/external/test262
Alternatively, you can check it out elsewhere and make
test/script/external/test262 a symbolic link to that directory. After
@@ -95,6 +95,11 @@
cd nashorn~jdk8/nashorn/make
ant test262
+
+Ant target to get/update external test suites:
+
+ ant externals
+ ant update-externals
These tests take time, so we have a parallelized runner for them that
takes advantage of all processor cores on the computer:
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
index 69c28b2..bb6abbc 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
@@ -50,8 +50,6 @@
import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
@@ -191,8 +189,6 @@
// stack: Collection
// pmap = PropertyMap.newMap(Collection<Property>);
mi.invokeStatic(PROPERTYMAP_TYPE, PROPERTYMAP_NEWMAP, PROPERTYMAP_NEWMAP_DESC);
- // pmap.setIsShared();
- mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_SETISSHARED, PROPERTYMAP_SETISSHARED_DESC);
// $nasgenmap$ = pmap;
mi.putStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
mi.returnVoid();
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
index d46f78c..67cbde4 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
@@ -33,10 +33,7 @@
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC;
@@ -171,9 +168,6 @@
private void loadMap(final MethodGenerator mi) {
if (memberCount > 0) {
mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
- // make sure we use duplicated PropertyMap so that original map
- // stays intact and so can be used for many globals.
- mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC);
}
}
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
index 3fdd7c6..e47f8b1 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
@@ -22,40 +22,62 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
package jdk.nashorn.internal.tools.nasgen;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.ScriptObject;
/**
* Details about a Java method or field annotated with any of the field/method
* annotations from the jdk.nashorn.internal.objects.annotations package.
*/
public final class MemberInfo implements Cloneable {
+ // class loader of this class
+ private static ClassLoader myLoader = MemberInfo.class.getClassLoader();
+
/**
* The different kinds of available class annotations
*/
public static enum Kind {
- /** This is a script class */
+
+ /**
+ * This is a script class
+ */
SCRIPT_CLASS,
- /** This is a constructor */
+ /**
+ * This is a constructor
+ */
CONSTRUCTOR,
- /** This is a function */
+ /**
+ * This is a function
+ */
FUNCTION,
- /** This is a getter */
+ /**
+ * This is a getter
+ */
GETTER,
- /** This is a setter */
+ /**
+ * This is a setter
+ */
SETTER,
- /** This is a property */
+ /**
+ * This is a property
+ */
PROPERTY,
- /** This is a specialized version of a function */
+ /**
+ * This is a specialized version of a function
+ */
SPECIALIZED_FUNCTION,
- /** This is a specialized version of a constructor */
+ /**
+ * This is a specialized version of a constructor
+ */
SPECIALIZED_CONSTRUCTOR
}
@@ -194,6 +216,7 @@
/**
* Check whether this MemberInfo is a getter that resides in the instance
+ *
* @return true if instance setter
*/
boolean isInstanceSetter() {
@@ -245,96 +268,201 @@
}
void verify() {
- if (kind == Kind.CONSTRUCTOR) {
- final Type returnType = Type.getReturnType(javaDesc);
- if (! returnType.toString().equals(OBJECT_DESC)) {
- error("return value should be of Object type, found" + returnType);
- }
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- if (argTypes.length < 2) {
- error("constructor methods should have at least 2 args");
- }
- if (! argTypes[0].equals(Type.BOOLEAN_TYPE)) {
- error("first argument should be of boolean type, found" + argTypes[0]);
- }
- if (! argTypes[1].toString().equals(OBJECT_DESC)) {
- error("second argument should be of Object type, found" + argTypes[0]);
- }
+ switch (kind) {
+ case CONSTRUCTOR: {
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isJSObjectType(returnType)) {
+ error("return value of a @Constructor method should be of Object type, found " + returnType);
+ }
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ if (argTypes.length < 2) {
+ error("@Constructor methods should have at least 2 args");
+ }
+ if (!argTypes[0].equals(Type.BOOLEAN_TYPE)) {
+ error("first argument of a @Constructor method should be of boolean type, found " + argTypes[0]);
+ }
+ if (!isJavaLangObject(argTypes[1])) {
+ error("second argument of a @Constructor method should be of Object type, found " + argTypes[0]);
+ }
- if (argTypes.length > 2) {
- for (int i = 2; i < argTypes.length - 1; i++) {
- if (! argTypes[i].toString().equals(OBJECT_DESC)) {
- error(i + "'th argument should be of Object type, found " + argTypes[i]);
+ if (argTypes.length > 2) {
+ for (int i = 2; i < argTypes.length - 1; i++) {
+ if (!isJavaLangObject(argTypes[i])) {
+ error(i + "'th argument of a @Constructor method should be of Object type, found " + argTypes[i]);
+ }
+ }
+
+ final String lastArgTypeDesc = argTypes[argTypes.length - 1].getDescriptor();
+ final boolean isVarArg = lastArgTypeDesc.equals(OBJECT_ARRAY_DESC);
+ if (!lastArgTypeDesc.equals(OBJECT_DESC) && !isVarArg) {
+ error("last argument of a @Constructor method is neither Object nor Object[] type: " + lastArgTypeDesc);
+ }
+
+ if (isVarArg && argTypes.length > 3) {
+ error("vararg of a @Constructor method has more than 3 arguments");
}
}
-
- final String lastArgType = argTypes[argTypes.length - 1].toString();
- final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC);
- if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) {
- error("last argument is neither Object nor Object[] type: " + lastArgType);
+ }
+ break;
+ case SPECIALIZED_CONSTRUCTOR: {
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isJSObjectType(returnType)) {
+ error("return value of a @SpecializedConstructor method should be a valid JS type, found " + returnType);
}
-
- if (isVarArg && argTypes.length > 3) {
- error("vararg constructor has more than 3 arguments");
- }
- }
- } else if (kind == Kind.FUNCTION) {
- final Type returnType = Type.getReturnType(javaDesc);
- if (! returnType.toString().equals(OBJECT_DESC)) {
- error("return value should be of Object type, found" + returnType);
- }
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- if (argTypes.length < 1) {
- error("function methods should have at least 1 arg");
- }
- if (! argTypes[0].toString().equals(OBJECT_DESC)) {
- error("first argument should be of Object type, found" + argTypes[0]);
- }
-
- if (argTypes.length > 1) {
- for (int i = 1; i < argTypes.length - 1; i++) {
- if (! argTypes[i].toString().equals(OBJECT_DESC)) {
- error(i + "'th argument should be of Object type, found " + argTypes[i]);
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ for (int i = 0; i < argTypes.length; i++) {
+ if (!isValidJSType(argTypes[i])) {
+ error(i + "'th argument of a @SpecializedConstructor method is not valid JS type, found " + argTypes[i]);
}
}
-
- final String lastArgType = argTypes[argTypes.length - 1].toString();
- final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC);
- if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) {
- error("last argument is neither Object nor Object[] type: " + lastArgType);
+ }
+ break;
+ case FUNCTION: {
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isValidJSType(returnType)) {
+ error("return value of a @Function method should be a valid JS type, found " + returnType);
+ }
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ if (argTypes.length < 1) {
+ error("@Function methods should have at least 1 arg");
+ }
+ if (!isJavaLangObject(argTypes[0])) {
+ error("first argument of a @Function method should be of Object type, found " + argTypes[0]);
}
- if (isVarArg && argTypes.length > 2) {
- error("vararg function has more than 2 arguments");
+ if (argTypes.length > 1) {
+ for (int i = 1; i < argTypes.length - 1; i++) {
+ if (!isJavaLangObject(argTypes[i])) {
+ error(i + "'th argument of a @Function method should be of Object type, found " + argTypes[i]);
+ }
+ }
+
+ final String lastArgTypeDesc = argTypes[argTypes.length - 1].getDescriptor();
+ final boolean isVarArg = lastArgTypeDesc.equals(OBJECT_ARRAY_DESC);
+ if (!lastArgTypeDesc.equals(OBJECT_DESC) && !isVarArg) {
+ error("last argument of a @Function method is neither Object nor Object[] type: " + lastArgTypeDesc);
+ }
+
+ if (isVarArg && argTypes.length > 2) {
+ error("vararg @Function method has more than 2 arguments");
+ }
}
}
- } else if (kind == Kind.GETTER) {
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- if (argTypes.length != 1) {
- error("getter methods should have one argument");
+ break;
+ case SPECIALIZED_FUNCTION: {
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isValidJSType(returnType)) {
+ error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType);
+ }
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ for (int i = 0; i < argTypes.length; i++) {
+ if (!isValidJSType(argTypes[i])) {
+ error(i + "'th argument of a @SpecializedFunction method is not valid JS type, found " + argTypes[i]);
+ }
+ }
}
- if (! argTypes[0].toString().equals(OBJECT_DESC)) {
- error("first argument of getter should be of Object type, found: " + argTypes[0]);
+ break;
+ case GETTER: {
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ if (argTypes.length != 1) {
+ error("@Getter methods should have one argument");
+ }
+ if (!isJavaLangObject(argTypes[0])) {
+ error("first argument of a @Getter method should be of Object type, found: " + argTypes[0]);
+ }
+
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isJavaLangObject(returnType)) {
+ error("return type of a @Getter method should be Object, found: " + javaDesc);
+ }
}
- if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) {
- error("return type of getter should not be void");
+ break;
+ case SETTER: {
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ if (argTypes.length != 2) {
+ error("@Setter methods should have two arguments");
+ }
+ if (!isJavaLangObject(argTypes[0])) {
+ error("first argument of a @Setter method should be of Object type, found: " + argTypes[0]);
+ }
+ if (!Type.getReturnType(javaDesc).toString().equals("V")) {
+ error("return type of of a @Setter method should be void, found: " + Type.getReturnType(javaDesc));
+ }
}
- } else if (kind == Kind.SETTER) {
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- if (argTypes.length != 2) {
- error("setter methods should have two arguments");
- }
- if (! argTypes[0].toString().equals(OBJECT_DESC)) {
- error("first argument of setter should be of Object type, found: " + argTypes[0]);
- }
- if (!Type.getReturnType(javaDesc).toString().equals("V")) {
- error("return type of setter should be void, found: " + Type.getReturnType(javaDesc));
+ break;
+ case PROPERTY: {
+ if (where == Where.CONSTRUCTOR) {
+ if (isStatic()) {
+ if (!isFinal()) {
+ error("static Where.CONSTRUCTOR @Property should be final");
+ }
+
+ if (!isJSPrimitiveType(Type.getType(javaDesc))) {
+ error("static Where.CONSTRUCTOR @Property should be a JS primitive");
+ }
+ }
+ } else if (where == Where.PROTOTYPE) {
+ if (isStatic()) {
+ if (!isFinal()) {
+ error("static Where.PROTOTYPE @Property should be final");
+ }
+
+ if (!isJSPrimitiveType(Type.getType(javaDesc))) {
+ error("static Where.PROTOTYPE @Property should be a JS primitive");
+ }
+ }
+ }
}
}
}
+ private static boolean isValidJSType(final Type type) {
+ return isJSPrimitiveType(type) || isJSObjectType(type);
+ }
+
+ private static boolean isJSPrimitiveType(final Type type) {
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ case Type.INT:
+ case Type.LONG:
+ case Type.DOUBLE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static boolean isJSObjectType(final Type type) {
+ return isJavaLangObject(type) || isJavaLangString(type) || isScriptObject(type);
+ }
+
+ private static boolean isJavaLangObject(final Type type) {
+ return type.getDescriptor().equals(OBJECT_DESC);
+ }
+
+ private static boolean isJavaLangString(final Type type) {
+ return type.getDescriptor().equals(STRING_DESC);
+ }
+
+ private static boolean isScriptObject(final Type type) {
+ if (type.getDescriptor().equals(SCRIPTOBJECT_DESC)) {
+ return true;
+ }
+
+ if (type.getSort() == Type.OBJECT) {
+ try {
+ final Class clazz = Class.forName(type.getClassName(), false, myLoader);
+ return ScriptObject.class.isAssignableFrom(clazz);
+ } catch (final ClassNotFoundException cnfe) {
+ return false;
+ }
+ }
+
+ return false;
+ }
+
private void error(final String msg) {
- throw new RuntimeException(javaName + javaDesc + " : " + msg);
+ throw new RuntimeException(javaName + " of type " + javaDesc + " : " + msg);
}
/**
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
index 475d732..479d1d3 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
@@ -349,19 +349,19 @@
// invokes, field get/sets
void invokeInterface(final String owner, final String method, final String desc) {
- super.visitMethodInsn(INVOKEINTERFACE, owner, method, desc);
+ super.visitMethodInsn(INVOKEINTERFACE, owner, method, desc, true);
}
void invokeVirtual(final String owner, final String method, final String desc) {
- super.visitMethodInsn(INVOKEVIRTUAL, owner, method, desc);
+ super.visitMethodInsn(INVOKEVIRTUAL, owner, method, desc, false);
}
void invokeSpecial(final String owner, final String method, final String desc) {
- super.visitMethodInsn(INVOKESPECIAL, owner, method, desc);
+ super.visitMethodInsn(INVOKESPECIAL, owner, method, desc, false);
}
void invokeStatic(final String owner, final String method, final String desc) {
- super.visitMethodInsn(INVOKESTATIC, owner, method, desc);
+ super.visitMethodInsn(INVOKESTATIC, owner, method, desc, false);
}
void putStatic(final String owner, final String field, final String desc) {
@@ -413,7 +413,7 @@
super.visitMethodInsn(INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
- "(Ljava/lang/String;)V");
+ "(Ljava/lang/String;)V", false);
}
// print the object on the top of the stack
@@ -426,6 +426,6 @@
super.visitMethodInsn(INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
- "(Ljava/lang/Object;)V");
+ "(Ljava/lang/Object;)V", false);
}
}
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
index 8bb1de5..7b1fff7 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
@@ -32,10 +32,7 @@
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX;
@@ -129,7 +126,6 @@
mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
// make sure we use duplicated PropertyMap so that original map
// stays intact and so can be used for many global.
- mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC);
mi.invokeSpecial(PROTOTYPEOBJECT_TYPE, INIT, SCRIPTOBJECT_INIT_DESC);
// initialize Function type fields
initFunctionFields(mi);
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
index 72250de..0ec233a 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
@@ -146,16 +146,16 @@
// call $clinit$ just before return from <clinit>
if (isStaticInit && opcode == RETURN) {
super.visitMethodInsn(INVOKESTATIC, scriptClassInfo.getJavaName(),
- $CLINIT$, DEFAULT_INIT_DESC);
+ $CLINIT$, DEFAULT_INIT_DESC, false);
}
super.visitInsn(opcode);
}
@Override
- public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
+ public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
if (isConstructor && opcode == INVOKESPECIAL &&
INIT.equals(name) && SCRIPTOBJECT_TYPE.equals(owner)) {
- super.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc, false);
if (memberCount > 0) {
// initialize @Property fields if needed
@@ -166,7 +166,7 @@
super.visitTypeInsn(NEW, clazz);
super.visitInsn(DUP);
super.visitMethodInsn(INVOKESPECIAL, clazz,
- INIT, DEFAULT_INIT_DESC);
+ INIT, DEFAULT_INIT_DESC, false);
super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(),
memInfo.getJavaName(), memInfo.getJavaDesc());
}
@@ -180,7 +180,7 @@
}
}
} else {
- super.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
index c4c1ab8..1d72418 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
@@ -45,11 +45,9 @@
@SuppressWarnings("javadoc")
public interface StringConstants {
// standard jdk types, methods
- static final Type TYPE_METHOD = Type.getType(Method.class);
static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class);
static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class);
static final Type TYPE_OBJECT = Type.getType(Object.class);
- static final Type TYPE_CLASS = Type.getType(Class.class);
static final Type TYPE_STRING = Type.getType(String.class);
static final Type TYPE_COLLECTION = Type.getType(Collection.class);
static final Type TYPE_COLLECTIONS = Type.getType(Collections.class);
@@ -63,6 +61,8 @@
static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName();
static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName();
static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor();
+ static final String STRING_TYPE = TYPE_STRING.getInternalName();
+ static final String STRING_DESC = TYPE_STRING.getDescriptor();
static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class);
static final String ARRAYLIST_TYPE = TYPE_ARRAYLIST.getInternalName();
static final String COLLECTION_TYPE = TYPE_COLLECTION.getInternalName();
@@ -104,10 +104,6 @@
static final String PROPERTYMAP_DESC = TYPE_PROPERTYMAP.getDescriptor();
static final String PROPERTYMAP_NEWMAP = "newMap";
static final String PROPERTYMAP_NEWMAP_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP, TYPE_COLLECTION);
- static final String PROPERTYMAP_DUPLICATE = "duplicate";
- static final String PROPERTYMAP_DUPLICATE_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
- static final String PROPERTYMAP_SETISSHARED = "setIsShared";
- static final String PROPERTYMAP_SETISSHARED_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
// PrototypeObject
static final String PROTOTYPEOBJECT_TYPE = TYPE_PROTOTYPEOBJECT.getInternalName();
@@ -135,6 +131,7 @@
// ScriptObject
static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName();
+ static final String SCRIPTOBJECT_DESC = TYPE_SCRIPTOBJECT.getDescriptor();
static final String SCRIPTOBJECT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_PROPERTYMAP);
static final String GETTER_PREFIX = "G$";
diff --git a/nashorn/make/BuildNashorn.gmk b/nashorn/make/BuildNashorn.gmk
index fc87044..a987874 100644
--- a/nashorn/make/BuildNashorn.gmk
+++ b/nashorn/make/BuildNashorn.gmk
@@ -77,7 +77,7 @@
$(RM) -rf $(@D)/jdk $(@D)/netscape
$(CP) -R -p $(NASHORN_OUTPUTDIR)/nashorn_classes/* $(@D)/
$(FIXPATH) $(JAVA) \
- -cp "$(NASHORN_OUTPUTDIR)/nasgen_classes$(PATH_SEP)$(NASHORN_OUTPUTDIR)/nashorn_classes" \
+ -Xbootclasspath/p:"$(NASHORN_OUTPUTDIR)/nasgen_classes$(PATH_SEP)$(NASHORN_OUTPUTDIR)/nashorn_classes" \
jdk.nashorn.internal.tools.nasgen.Main $(@D) jdk.nashorn.internal.objects $(@D)
$(TOUCH) $@
diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml
index 7d1f42a..4d23f22 100644
--- a/nashorn/make/build.xml
+++ b/nashorn/make/build.xml
@@ -42,6 +42,9 @@
<condition property="hg.executable" value="/usr/local/bin/hg" else="hg">
<available file="/usr/local/bin/hg"/>
</condition>
+ <condition property="git.executable" value="/usr/local/bin/git" else="git">
+ <available file="/usr/local/bin/git"/>
+ </condition>
<!-- check if JDK already has ASM classes -->
<available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/>
<!-- check if testng.jar is avaiable -->
@@ -122,6 +125,7 @@
<compilerarg value="-Xlint:unchecked"/>
<compilerarg value="-Xlint:deprecation"/>
<compilerarg value="-XDignore.symbol.file"/>
+ <compilerarg value="-Xdiags:verbose"/>
</javac>
<copy todir="${build.classes.dir}/META-INF/services">
<fileset dir="${meta.inf.dir}/services/"/>
@@ -240,6 +244,7 @@
<compilerarg value="-J-Djava.ext.dirs="/>
<compilerarg value="-Xlint:unchecked"/>
<compilerarg value="-Xlint:deprecation"/>
+ <compilerarg value="-Xdiags:verbose"/>
</javac>
<copy todir="${build.test.classes.dir}/META-INF/services">
@@ -250,6 +255,10 @@
<fileset dir="${test.src.dir}/jdk/nashorn/internal/runtime/resources"/>
</copy>
+ <copy todir="${build.test.classes.dir}/jdk/nashorn/api/scripting/resources">
+ <fileset dir="${test.src.dir}/jdk/nashorn/api/scripting/resources"/>
+ </copy>
+
<!-- tests that check nashorn internals and internal API -->
<jar jarfile="${nashorn.internal.tests.jar}">
<fileset dir="${build.test.classes.dir}" excludes="**/api/**"/>
@@ -279,6 +288,11 @@
permission java.security.AllPermission;
};
+grant codeBase "file:/${basedir}/test/script/maptests/*" {
+ permission java.io.FilePermission "${basedir}/test/script/maptests/*","read";
+ permission java.lang.RuntimePermission "nashorn.debugMode";
+};
+
grant codeBase "file:/${basedir}/test/script/basic/*" {
permission java.io.FilePermission "${basedir}/test/script/-", "read";
permission java.io.FilePermission "$${user.dir}", "read";
@@ -459,18 +473,17 @@
<!-- test262 test suite -->
<target name="get-test262" depends="init" unless="${test-sys-prop.external.test262}">
- <!-- clone test262 mercurial repo -->
- <exec executable="${hg.executable}">
+ <!-- clone test262 git repo -->
+ <exec executable="${git.executable}">
<arg value="clone"/>
- <arg value="http://hg.ecmascript.org/tests/test262"/>
+ <arg value="https://github.com/tc39/test262"/>
<arg value="${test.external.dir}/test262"/>
</exec>
</target>
<target name="update-test262" depends="init" if="${test-sys-prop.external.test262}">
- <!-- update test262 mercurial repo -->
- <exec executable="${hg.executable}" dir="${test.external.dir}/test262">
+ <!-- update test262 git repo -->
+ <exec executable="${git.executable}" dir="${test.external.dir}/test262">
<arg value="pull"/>
- <arg value="-u"/>
</exec>
</target>
diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties
index c3ffca4..8c5dd4f 100644
--- a/nashorn/make/project.properties
+++ b/nashorn/make/project.properties
@@ -112,6 +112,7 @@
test.dir=test
test.script.dir=test/script
test.basic.dir=test/script/basic
+test.maptests.dir=test/script/maptests
test.error.dir=test/script/error
test.sandbox.dir=test/script/sandbox
test.trusted.dir=test/script/trusted
@@ -121,7 +122,7 @@
testjfx.dir=${test.script.dir}/jfx
test-sys-prop.test.dir=${test.dir}
-test-sys-prop.test.js.roots=${test.basic.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir}
+test-sys-prop.test.js.roots=${test.basic.dir} ${test.maptests.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir}
test-sys-prop.test262.suite.dir=${test262.suite.dir}
test-sys-prop.es5conform.testcases.dir=${test.external.dir}/ES5Conform/TestCases
test-sys-prop.test.basic.dir=${test.basic.dir}
@@ -201,7 +202,7 @@
# test262 test frameworks
test262-test-sys-prop.test.js.framework=\
- --class-cache-size=0 \
+ --class-cache-size=10 \
--no-java \
--no-typed-arrays \
-timezone=PST \
@@ -264,7 +265,7 @@
run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy
# VM options for script tests with @fork option
-test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}
+test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -cp ${run.test.classpath}
# path of rhino.jar for benchmarks
rhino.jar=
diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java
index d5ec5bb..a5f8c24 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java
@@ -29,6 +29,7 @@
import java.util.List;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.ScriptObject;
/**
* This is base exception for all Nashorn exceptions. These originate from
@@ -44,11 +45,13 @@
@SuppressWarnings("serial")
public abstract class NashornException extends RuntimeException {
// script file name
- private final String fileName;
+ private String fileName;
// script line number
- private final int line;
+ private int line;
// script column number
- private final int column;
+ private int column;
+ // underlying ECMA error object - lazily initialized
+ private Object ecmaError;
/** script source name used for "engine.js" */
public static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js";
@@ -122,6 +125,15 @@
}
/**
+ * Set the source file name for this {@code NashornException}
+ *
+ * @param fileName the file name
+ */
+ public final void setFileName(final String fileName) {
+ this.fileName = fileName;
+ }
+
+ /**
* Get the line number for this {@code NashornException}
*
* @return the line number
@@ -131,15 +143,33 @@
}
/**
+ * Set the line number for this {@code NashornException}
+ *
+ * @param line the line number
+ */
+ public final void setLineNumber(final int line) {
+ this.line = line;
+ }
+
+ /**
* Get the column for this {@code NashornException}
*
- * @return the column
+ * @return the column number
*/
public final int getColumnNumber() {
return column;
}
/**
+ * Set the column for this {@code NashornException}
+ *
+ * @param column the column number
+ */
+ public final void setColumnNumber(final int column) {
+ this.column = column;
+ }
+
+ /**
* Returns array javascript stack frames from the given exception object.
*
* @param exception exception from which stack frames are retrieved and filtered
@@ -155,6 +185,11 @@
if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) {
methodName = "<program>";
}
+
+ if (methodName.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName())) {
+ methodName = "<anonymous>";
+ }
+
filtered.add(new StackTraceElement(className, methodName,
st.getFileName(), st.getLineNumber()));
}
@@ -188,4 +223,43 @@
}
return buf.toString();
}
+
+ protected Object getThrown() {
+ return null;
+ }
+
+ protected NashornException initEcmaError(final ScriptObject global) {
+ if (ecmaError != null) {
+ return this; // initialized already!
+ }
+
+ final Object thrown = getThrown();
+ if (thrown instanceof ScriptObject) {
+ setEcmaError(ScriptObjectMirror.wrap(thrown, global));
+ } else {
+ setEcmaError(thrown);
+ }
+
+ return this;
+ }
+
+ /**
+ * Return the underlying ECMA error object, if available.
+ *
+ * @return underlying ECMA Error object's mirror or whatever was thrown
+ * from script such as a String, Number or a Boolean.
+ */
+ public Object getEcmaError() {
+ return ecmaError;
+ }
+
+ /**
+ * Return the underlying ECMA error object, if available.
+ *
+ * @param ecmaError underlying ECMA Error object's mirror or whatever was thrown
+ * from script such as a String, Number or a Boolean.
+ */
+ public void setEcmaError(final Object ecmaError) {
+ this.ecmaError = ecmaError;
+ }
}
diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
index 83b0bee..9c14359 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
@@ -57,9 +57,9 @@
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -99,7 +99,7 @@
private final boolean _global_per_engine;
// This is the initial default Nashorn global object.
// This is used as "shared" global if above option is true.
- private final ScriptObject global;
+ private final Global global;
// initialized bit late to be made 'final'.
// Property object for "context" property of global object.
private volatile Property contextProperty;
@@ -264,7 +264,7 @@
public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
if (ctxt != null) {
final int scope = ctxt.getAttributesScope(name);
- final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
+ final Global ctxtGlobal = getNashornGlobalFrom(ctxt);
if (scope != -1) {
return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
}
@@ -317,7 +317,7 @@
}
ScriptObject realSelf = null;
- ScriptObject realGlobal = null;
+ Global realGlobal = null;
if(thiz == null) {
// making interface out of global functions
realSelf = realGlobal = getNashornGlobalFrom(context);
@@ -346,7 +346,7 @@
}
try {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != realGlobal);
try {
if (globalChanged) {
@@ -371,7 +371,7 @@
}
// Retrieve nashorn Global object for a given ScriptContext object
- private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) {
+ private Global getNashornGlobalFrom(final ScriptContext ctxt) {
if (_global_per_engine) {
// shared single global object for all ENGINE_SCOPE Bindings
return global;
@@ -380,18 +380,18 @@
final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE);
// is this Nashorn's own Bindings implementation?
if (bindings instanceof ScriptObjectMirror) {
- final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)bindings);
- if (sobj != null) {
- return sobj;
+ final Global glob = globalFromMirror((ScriptObjectMirror)bindings);
+ if (glob != null) {
+ return glob;
}
}
// Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
Object scope = bindings.get(NASHORN_GLOBAL);
if (scope instanceof ScriptObjectMirror) {
- final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)scope);
- if (sobj != null) {
- return sobj;
+ final Global glob = globalFromMirror((ScriptObjectMirror)scope);
+ if (glob != null) {
+ return glob;
}
}
@@ -399,14 +399,14 @@
// Create new global instance mirror and associate with the Bindings.
final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
bindings.put(NASHORN_GLOBAL, mirror);
- return mirror.getScriptObject();
+ return mirror.getHomeGlobal();
}
// Retrieve nashorn Global object from a given ScriptObjectMirror
- private ScriptObject globalFromMirror(final ScriptObjectMirror mirror) {
+ private Global globalFromMirror(final ScriptObjectMirror mirror) {
ScriptObject sobj = mirror.getScriptObject();
- if (sobj instanceof GlobalObject && isOfContext(sobj, nashornContext)) {
- return sobj;
+ if (sobj instanceof Global && isOfContext((Global)sobj, nashornContext)) {
+ return (Global)sobj;
}
return null;
@@ -414,15 +414,15 @@
// Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
- final ScriptObject newGlobal = createNashornGlobal(ctxt);
+ final Global newGlobal = createNashornGlobal(ctxt);
return new ScriptObjectMirror(newGlobal, newGlobal);
}
// Create a new Nashorn Global object
- private ScriptObject createNashornGlobal(final ScriptContext ctxt) {
- final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
+ private Global createNashornGlobal(final ScriptContext ctxt) {
+ final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
@Override
- public ScriptObject run() {
+ public Global run() {
try {
return nashornContext.newGlobal();
} catch (final RuntimeException e) {
@@ -460,7 +460,7 @@
}
// scripts should see "context" and "engine" as variables in the given global object
- private void setContextVariables(final ScriptObject ctxtGlobal, final ScriptContext ctxt) {
+ private void setContextVariables(final Global ctxtGlobal, final ScriptContext ctxt) {
// set "context" global variable via contextProperty - because this
// property is non-writable
contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
@@ -470,7 +470,7 @@
}
// if no arguments passed, expose it
if (! (args instanceof ScriptObject)) {
- args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
+ args = ctxtGlobal.wrapAsObject(args);
ctxtGlobal.set("arguments", args, false);
}
}
@@ -478,16 +478,19 @@
private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
name.getClass(); // null check
+ Global invokeGlobal = null;
ScriptObjectMirror selfMirror = null;
if (selfObject instanceof ScriptObjectMirror) {
selfMirror = (ScriptObjectMirror)selfObject;
if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) {
throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
}
+ invokeGlobal = selfMirror.getHomeGlobal();
} else if (selfObject instanceof ScriptObject) {
// invokeMethod called from script code - in which case we may get 'naked' ScriptObject
// Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
+ invokeGlobal = oldGlobal;
if (oldGlobal == null) {
throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
}
@@ -499,7 +502,8 @@
selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
} else if (selfObject == null) {
// selfObject is null => global function call
- final ScriptObject ctxtGlobal = getNashornGlobalFrom(context);
+ final Global ctxtGlobal = getNashornGlobalFrom(context);
+ invokeGlobal = ctxtGlobal;
selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(ctxtGlobal, ctxtGlobal);
}
@@ -511,7 +515,7 @@
if (cause instanceof NoSuchMethodException) {
throw (NoSuchMethodException)cause;
}
- throwAsScriptException(e);
+ throwAsScriptException(e, invokeGlobal);
throw new AssertionError("should not reach here");
}
}
@@ -528,11 +532,11 @@
return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
}
- private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final ScriptObject ctxtGlobal) throws ScriptException {
+ private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
if (script == null) {
return null;
}
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != ctxtGlobal);
try {
if (globalChanged) {
@@ -545,7 +549,7 @@
}
return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
} catch (final Exception e) {
- throwAsScriptException(e);
+ throwAsScriptException(e, ctxtGlobal);
throw new AssertionError("should not reach here");
} finally {
if (globalChanged) {
@@ -554,7 +558,7 @@
}
}
- private static void throwAsScriptException(final Exception e) throws ScriptException {
+ private static void throwAsScriptException(final Exception e, final Global global) throws ScriptException {
if (e instanceof ScriptException) {
throw (ScriptException)e;
} else if (e instanceof NashornException) {
@@ -562,6 +566,7 @@
final ScriptException se = new ScriptException(
ne.getMessage(), ne.getFileName(),
ne.getLineNumber(), ne.getColumnNumber());
+ ne.initEcmaError(global);
se.initCause(e);
throw se;
} else if (e instanceof RuntimeException) {
@@ -577,7 +582,7 @@
return new CompiledScript() {
@Override
public Object eval(final ScriptContext ctxt) throws ScriptException {
- final ScriptObject globalObject = getNashornGlobalFrom(ctxt);
+ final Global globalObject = getNashornGlobalFrom(ctxt);
// Are we running the script in the correct global?
if (func.getScope() == globalObject) {
return evalImpl(func, ctxt, globalObject);
@@ -597,8 +602,8 @@
return compileImpl(source, getNashornGlobalFrom(ctxt));
}
- private ScriptFunction compileImpl(final Source source, final ScriptObject newGlobal) throws ScriptException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ private ScriptFunction compileImpl(final Source source, final Global newGlobal) throws ScriptException {
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != newGlobal);
try {
if (globalChanged) {
@@ -607,7 +612,7 @@
return nashornContext.compileScript(source, newGlobal);
} catch (final Exception e) {
- throwAsScriptException(e);
+ throwAsScriptException(e, newGlobal);
throw new AssertionError("should not reach here");
} finally {
if (globalChanged) {
@@ -623,6 +628,11 @@
continue;
}
+ // skip check for default methods - non-abstract, interface methods
+ if (! Modifier.isAbstract(method.getModifiers())) {
+ continue;
+ }
+
Object obj = sobj.get(method.getName());
if (! (obj instanceof ScriptFunction)) {
return false;
@@ -631,8 +641,7 @@
return true;
}
- private static boolean isOfContext(final ScriptObject global, final Context context) {
- assert global instanceof GlobalObject: "Not a Global object";
- return ((GlobalObject)global).isOfContext(context);
+ private static boolean isOfContext(final Global global, final Context context) {
+ return global.isOfContext(context);
}
}
diff --git a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
index 911f166..b125533 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
@@ -25,6 +25,7 @@
package jdk.nashorn.api.scripting;
+import java.nio.ByteBuffer;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
@@ -41,9 +42,10 @@
import java.util.Set;
import java.util.concurrent.Callable;
import javax.script.Bindings;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -62,7 +64,7 @@
private static final AccessControlContext GET_CONTEXT_ACC_CTXT = getContextAccCtxt();
private final ScriptObject sobj;
- private final ScriptObject global;
+ private final Global global;
private final boolean strict;
@Override
@@ -93,7 +95,7 @@
@Override
public Object call(final Object thiz, final Object... args) {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
@@ -108,6 +110,8 @@
}
throw new RuntimeException("not a function: " + toString());
+ } catch (final NashornException ne) {
+ throw ne.initEcmaError(global);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
@@ -121,7 +125,7 @@
@Override
public Object newObject(final Object... args) {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
@@ -135,6 +139,8 @@
}
throw new RuntimeException("not a constructor: " + toString());
+ } catch (final NashornException ne) {
+ throw ne.initEcmaError(global);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
@@ -165,7 +171,7 @@
public Object callMember(final String functionName, final Object... args) {
functionName.getClass(); // null check
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
@@ -182,6 +188,8 @@
}
throw new NoSuchMethodException("No such function " + functionName);
+ } catch (final NashornException ne) {
+ throw ne.initEcmaError(global);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
@@ -253,6 +261,22 @@
});
}
+ /**
+ * Nashorn extension: setIndexedPropertiesToExternalArrayData.
+ * set indexed properties be exposed from a given nio ByteBuffer.
+ *
+ * @param buf external buffer - should be a nio ByteBuffer
+ */
+ public void setIndexedPropertiesToExternalArrayData(final ByteBuffer buf) {
+ inGlobal(new Callable<Void>() {
+ @Override public Void call() {
+ sobj.setArray(ArrayData.allocate(buf));
+ return null;
+ }
+ });
+ }
+
+
@Override
public boolean isInstance(final Object obj) {
if (! (obj instanceof ScriptObjectMirror)) {
@@ -618,7 +642,7 @@
*/
public static Object wrap(final Object obj, final Object homeGlobal) {
if(obj instanceof ScriptObject) {
- return homeGlobal instanceof ScriptObject ? new ScriptObjectMirror((ScriptObject)obj, (ScriptObject)homeGlobal) : obj;
+ return homeGlobal instanceof Global ? new ScriptObjectMirror((ScriptObject)obj, (Global)homeGlobal) : obj;
}
if(obj instanceof ConsString) {
return obj.toString();
@@ -686,13 +710,13 @@
// package-privates below this.
- ScriptObjectMirror(final ScriptObject sobj, final ScriptObject global) {
+ ScriptObjectMirror(final ScriptObject sobj, final Global global) {
assert sobj != null : "ScriptObjectMirror on null!";
- assert global instanceof GlobalObject : "global is not a GlobalObject";
+ assert global != null : "home Global is null";
this.sobj = sobj;
this.global = global;
- this.strict = ((GlobalObject)global).isStrictContext();
+ this.strict = global.isStrictContext();
}
// accessors for script engine
@@ -700,7 +724,7 @@
return sobj;
}
- ScriptObject getHomeGlobal() {
+ Global getHomeGlobal() {
return global;
}
@@ -710,13 +734,15 @@
// internals only below this.
private <V> V inGlobal(final Callable<V> callable) {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
if (globalChanged) {
Context.setGlobal(global);
}
try {
return callable.call();
+ } catch (final NashornException ne) {
+ throw ne.initEcmaError(global);
} catch (final RuntimeException e) {
throw e;
} catch (final Exception e) {
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java
index 177cfef..61ccb71 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java
@@ -375,10 +375,11 @@
* @return Symbol for given name or null for redefinition.
*/
private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) {
- int flags = symbolFlags;
- Symbol symbol = findSymbol(block, name); // Locate symbol.
+ int flags = symbolFlags;
+ Symbol symbol = findSymbol(block, name); // Locate symbol.
+ boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL;
- if ((flags & KINDMASK) == IS_GLOBAL) {
+ if (isGlobal) {
flags |= IS_SCOPE;
}
@@ -414,6 +415,8 @@
// Determine where to create it.
if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) {
symbolBlock = block; //internal vars are always defined in the block closest to them
+ } else if (isGlobal) {
+ symbolBlock = lc.getOutermostFunction().getBody();
} else {
symbolBlock = lc.getFunctionBody(function);
}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
index c3b1dbe..e0ca67a 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -685,7 +685,7 @@
private void scopeCall(final IdentNode node, final int flags) {
load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3
// ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
- method.loadNull(); //the 'this'
+ method.loadUndefined(Type.OBJECT); //the 'this' object
method.dynamicCall(callNodeType, 2 + loadArgs(args), flags);
}
@@ -818,7 +818,7 @@
protected boolean enterDefault(final Node node) {
// Load up function.
load(function, Type.OBJECT); //TODO, e.g. booleans can be used as functions
- method.loadNull(); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
+ method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags() | CALLSITE_SCOPE);
return false;
@@ -2023,8 +2023,6 @@
return false;
}
- method._new(ECMAException.class).dup();
-
final Source source = lc.getCurrentFunction().getSource();
final Expression expression = throwNode.getExpression();
@@ -2037,7 +2035,7 @@
method.load(source.getName());
method.load(line);
method.load(column);
- method.invoke(ECMAException.THROW_INIT);
+ method.invoke(ECMAException.CREATE);
method.athrow();
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java b/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
index d27bdd9..dcf1b1b 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
@@ -158,7 +158,7 @@
if (scopeCalls.containsKey(scopeCall)) {
return scopeCalls.get(scopeCall);
}
- scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall"));
+ scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName(":scopeCall"));
scopeCalls.put(scopeCall, scopeCall);
return scopeCall;
}
@@ -177,7 +177,7 @@
if (scopeCalls.containsKey(scopeCall)) {
return scopeCalls.get(scopeCall);
}
- scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall"));
+ scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName(":scopeCall"));
scopeCalls.put(scopeCall, scopeCall);
return scopeCall;
}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
index 24173c3..b53b8fd 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
@@ -85,6 +85,8 @@
private Source source;
+ private String sourceName;
+
private final Map<String, byte[]> bytecode;
private final Set<CompileUnit> compileUnits;
@@ -267,6 +269,7 @@
append('$').
append(safeSourceName(functionNode.getSource()));
this.source = functionNode.getSource();
+ this.sourceName = functionNode.getSourceName();
this.scriptName = sb.toString();
}
@@ -573,7 +576,7 @@
}
private CompileUnit initCompileUnit(final String unitClassName, final long initialWeight) {
- final ClassEmitter classEmitter = new ClassEmitter(env, source.getName(), unitClassName, strict);
+ final ClassEmitter classEmitter = new ClassEmitter(env, sourceName, unitClassName, strict);
final CompileUnit compileUnit = new CompileUnit(unitClassName, classEmitter, initialWeight);
classEmitter.begin();
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
index fb347c7..16f08b8 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
@@ -41,6 +41,7 @@
*/
public enum CompilerConstants {
+
/** the __FILE__ variable */
__FILE__,
@@ -75,7 +76,7 @@
DEFAULT_SCRIPT_NAME("Script"),
/** function prefix for anonymous functions */
- FUNCTION_PREFIX("function$"),
+ ANON_FUNCTION_PREFIX("L:"),
/** method name for Java method that is script entry point */
RUN_SCRIPT("runScript"),
@@ -149,26 +150,31 @@
ALLOCATE("allocate"),
/** prefix for split methods, @see Splitter */
- SPLIT_PREFIX("$split"),
+ SPLIT_PREFIX(":split"),
/** prefix for split array method and slot */
- SPLIT_ARRAY_ARG("split_array", 3),
+ SPLIT_ARRAY_ARG(":split_array", 3),
/** get string from constant pool */
- GET_STRING("$getString"),
+ GET_STRING(":getString"),
/** get map */
- GET_MAP("$getMap"),
+ GET_MAP(":getMap"),
/** get map */
- SET_MAP("$setMap"),
+ SET_MAP(":setMap"),
/** get array prefix */
- GET_ARRAY_PREFIX("$get"),
+ GET_ARRAY_PREFIX(":get"),
/** get array suffix */
GET_ARRAY_SUFFIX("$array");
+ /**
+ * Prefix used for internal methods generated in script clases.
+ */
+ public static final String INTERNAL_METHOD_PREFIX = ":";
+
private final String symbolName;
private final Class<?> type;
private final int slot;
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java b/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java
index 631cdb3..292f167 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java
@@ -25,6 +25,9 @@
package jdk.nashorn.internal.codegen;
+import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.PropertyMap;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -110,6 +113,43 @@
}
/**
+ * {@link PropertyMap} wrapper class that provides implementations for the {@code hashCode} and {@code equals}
+ * methods that are based on the map layout. {@code PropertyMap} itself inherits the identity based implementations
+ * from {@code java.lang.Object}.
+ */
+ private static class PropertyMapWrapper {
+ private final PropertyMap propertyMap;
+ private final int hashCode;
+
+ public PropertyMapWrapper(final PropertyMap map) {
+ int hash = 0;
+ for (final Property property : map.getProperties()) {
+ hash = hash << 7 ^ hash >> 7;
+ hash ^= property.hashCode();
+ }
+ this.hashCode = hash;
+ this.propertyMap = map;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (!(other instanceof PropertyMapWrapper)) {
+ return false;
+ }
+
+ final Property[] ownProperties = propertyMap.getProperties();
+ final Property[] otherProperties = ((PropertyMapWrapper) other).propertyMap.getProperties();
+
+ return Arrays.equals(ownProperties, otherProperties);
+ }
+ }
+
+ /**
* Constructor
*/
ConstantData() {
@@ -145,7 +185,14 @@
* @return the index in the constant pool that the object was given
*/
public int add(final Object object) {
- final Object entry = object.getClass().isArray() ? new ArrayWrapper(object) : object;
+ final Object entry;
+ if (object.getClass().isArray()) {
+ entry = new ArrayWrapper(object);
+ } else if (object instanceof PropertyMap) {
+ entry = new PropertyMapWrapper((PropertyMap) object);
+ } else {
+ entry = object;
+ }
final Integer value = objectMap.get(entry);
if (value != null) {
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
index 9b6d12a..91129ec 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
@@ -1130,7 +1130,11 @@
popType(Type.OBJECT);
}
- method.visitMethodInsn(opcode, className, methodName, methodDescriptor);
+ if (opcode == INVOKEINTERFACE) {
+ method.visitMethodInsn(opcode, className, methodName, methodDescriptor, true);
+ } else {
+ method.visitMethodInsn(opcode, className, methodName, methodDescriptor, false);
+ }
if (returnType != null) {
pushType(returnType);
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java b/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
index c7dfb40..da29ac0 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
@@ -156,7 +156,7 @@
if (isCall) {
method.convert(Type.OBJECT);
// ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
- method.loadNull();
+ method.loadUndefined(Type.OBJECT);
int slot = 2;
for (final Type type : paramTypes) {
method.load(type, slot++);
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
index e7c7895..4799c26 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
@@ -261,7 +261,7 @@
}
static void invokeStatic(final MethodVisitor method, final Call call) {
- method.visitMethodInsn(INVOKESTATIC, call.className(), call.name(), call.descriptor());
+ method.visitMethodInsn(INVOKESTATIC, call.className(), call.name(), call.descriptor(), false);
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
index b0998ae..a0f6a78 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
@@ -29,6 +29,7 @@
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.Compiler;
@@ -138,6 +139,9 @@
/** Function flags. */
private final int flags;
+ /** //@ sourceURL or //# sourceURL for program function nodes */
+ private final String sourceURL;
+
private final int lineNumber;
/** Is anonymous function flag. */
@@ -160,11 +164,11 @@
public static final int HAS_EVAL = 1 << 5;
/** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
- public static final int HAS_NESTED_EVAL = 1 << 6;
+ public static final int HAS_NESTED_EVAL = 1 << 6;
/** Does this function have any blocks that create a scope? This is used to determine if the function needs to
* have a local variable slot for the scope symbol. */
- public static final int HAS_SCOPE_BLOCK = 1 << 7;
+ public static final int HAS_SCOPE_BLOCK = 1 << 7;
/**
* Flag this function as one that defines the identifier "arguments" as a function parameter or nested function
@@ -193,6 +197,9 @@
/** Can this function be specialized? */
public static final int CAN_SPECIALIZE = 1 << 14;
+ /** Does this function use the "this" keyword? */
+ public static final int USES_THIS = 1 << 15;
+
/** Does this function or any nested functions contain an eval? */
private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
@@ -223,6 +230,7 @@
* @param parameters parameter list
* @param kind kind of function as in {@link FunctionNode.Kind}
* @param flags initial flags
+ * @param sourceURL sourceURL specified in script (optional)
*/
public FunctionNode(
final Source source,
@@ -235,7 +243,8 @@
final String name,
final List<IdentNode> parameters,
final FunctionNode.Kind kind,
- final int flags) {
+ final int flags,
+ final String sourceURL) {
super(token, finish);
this.source = source;
@@ -250,6 +259,7 @@
this.compilationState = EnumSet.of(CompilationState.INITIALIZED);
this.declaredSymbols = new HashSet<>();
this.flags = flags;
+ this.sourceURL = sourceURL;
this.compileUnit = null;
this.body = null;
this.snapshot = null;
@@ -260,6 +270,7 @@
final FunctionNode functionNode,
final long lastToken,
final int flags,
+ final String sourceURL,
final String name,
final Type returnType,
final CompileUnit compileUnit,
@@ -271,6 +282,7 @@
super(functionNode);
this.lineNumber = functionNode.lineNumber;
this.flags = flags;
+ this.sourceURL = sourceURL;
this.name = name;
this.returnType = returnType;
this.compileUnit = compileUnit;
@@ -308,6 +320,38 @@
}
/**
+ * get source name - sourceURL or name derived from Source.
+ *
+ * @return name for the script source
+ */
+ public String getSourceName() {
+ return (sourceURL != null)? sourceURL : source.getName();
+ }
+
+ /**
+ * get the sourceURL
+ * @return the sourceURL
+ */
+ public String getSourceURL() {
+ return sourceURL;
+ }
+
+ /**
+ * Set the sourceURL
+ *
+ * @param lc lexical context
+ * @param newSourceURL source url string to set
+ * @return function node or a new one if state was changed
+ */
+ public FunctionNode setSourceURL(final LexicalContext lc, final String newSourceURL) {
+ if (Objects.equals(sourceURL, newSourceURL)) {
+ return this;
+ }
+
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, newSourceURL, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
+ }
+
+ /**
* Returns the line number.
* @return the line number.
*/
@@ -335,7 +379,7 @@
if (this.snapshot == null) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
}
/**
@@ -351,7 +395,7 @@
if (isProgram() || parameters.isEmpty()) {
return this; //never specialize anything that won't be recompiled
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
}
/**
@@ -409,7 +453,7 @@
}
final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
newState.add(state);
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
}
/**
@@ -430,7 +474,7 @@
if (this.hints == hints) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -483,7 +527,7 @@
if (this.flags == flags) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
@Override
@@ -550,6 +594,15 @@
}
/**
+ * Return {@code true} if this function makes use of the {@code this} object.
+ *
+ * @return true if function uses {@code this} object
+ */
+ public boolean usesThis() {
+ return getFlag(USES_THIS);
+ }
+
+ /**
* Get the identifier for this function, this is its symbol.
* @return the identifier as an IdentityNode
*/
@@ -593,7 +646,7 @@
if(this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags | (body.needsScope() ? FunctionNode.HAS_SCOPE_BLOCK : 0), name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags | (body.needsScope() ? FunctionNode.HAS_SCOPE_BLOCK : 0), sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -688,7 +741,7 @@
if (this.lastToken == lastToken) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -710,7 +763,7 @@
if (this.name.equals(name)) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -760,7 +813,7 @@
if (this.parameters == parameters) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -825,6 +878,7 @@
this,
lastToken,
flags,
+ sourceURL,
name,
type,
compileUnit,
@@ -863,7 +917,7 @@
if (this.compileUnit == compileUnit) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
index b373162..e39c521 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
@@ -67,12 +67,8 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
AccessorPropertyDescriptor(final boolean configurable, final boolean enumerable, final Object get, final Object set, final Global global) {
- super(global.getObjectPrototype(), global.getAccessorPropertyDescriptorMap());
+ super(global.getObjectPrototype(), $nasgenmap$);
this.configurable = configurable;
this.enumerable = enumerable;
this.get = get;
@@ -185,6 +181,18 @@
}
@Override
+ public boolean hasAndEquals(final PropertyDescriptor otherDesc) {
+ if (! (otherDesc instanceof AccessorPropertyDescriptor)) {
+ return false;
+ }
+ final AccessorPropertyDescriptor other = (AccessorPropertyDescriptor)otherDesc;
+ return (!has(CONFIGURABLE) || sameValue(configurable, other.configurable)) &&
+ (!has(ENUMERABLE) || sameValue(enumerable, other.enumerable)) &&
+ (!has(GET) || sameValue(get, other.get)) &&
+ (!has(SET) || sameValue(set, other.set));
+ }
+
+ @Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
diff --git a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
index ecf8bec..c29af85 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
@@ -42,12 +42,8 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength, final Global global) {
- super(global.getArrayBufferViewMap());
+ super($nasgenmap$);
checkConstructorArgs(buffer, byteOffset, elementLength);
this.setProto(getPrototype(global));
this.setArray(factory().createArrayData(buffer, byteOffset, elementLength));
@@ -386,7 +382,7 @@
return (int) (length & Integer.MAX_VALUE);
}
- protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) {
+ protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) {
final ArrayBufferView arrayView = ((ArrayBufferView)self);
final int elementLength = arrayView.elementLength();
final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
diff --git a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
index ef3f0a3..e117c7e 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
@@ -64,12 +64,8 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
DataPropertyDescriptor(final boolean configurable, final boolean enumerable, final boolean writable, final Object value, final Global global) {
- super(global.getObjectPrototype(), global.getDataPropertyDescriptorMap());
+ super(global.getObjectPrototype(), $nasgenmap$);
this.configurable = configurable;
this.enumerable = enumerable;
this.writable = writable;
@@ -172,6 +168,19 @@
}
@Override
+ public boolean hasAndEquals(final PropertyDescriptor otherDesc) {
+ if (! (otherDesc instanceof DataPropertyDescriptor)) {
+ return false;
+ }
+
+ final DataPropertyDescriptor other = (DataPropertyDescriptor)otherDesc;
+ return (!has(CONFIGURABLE) || sameValue(configurable, other.configurable)) &&
+ (!has(ENUMERABLE) || sameValue(enumerable, other.enumerable)) &&
+ (!has(WRITABLE) || sameValue(writable, other.writable)) &&
+ (!has(VALUE) || sameValue(value, other.value));
+ }
+
+ @Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
diff --git a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
index f5662ef..19cc8b6 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
@@ -55,12 +55,8 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
GenericPropertyDescriptor(final boolean configurable, final boolean enumerable, final Global global) {
- super(global.getObjectPrototype(), global.getGenericPropertyDescriptorMap());
+ super(global.getObjectPrototype(), $nasgenmap$);
this.configurable = configurable;
this.enumerable = enumerable;
}
@@ -149,6 +145,23 @@
}
@Override
+ public boolean hasAndEquals(final PropertyDescriptor other) {
+ if (has(CONFIGURABLE) && other.has(CONFIGURABLE)) {
+ if (isConfigurable() != other.isConfigurable()) {
+ return false;
+ }
+ }
+
+ if (has(ENUMERABLE) && other.has(ENUMERABLE)) {
+ if (isEnumerable() != other.isEnumerable()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
diff --git a/nashorn/src/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk/nashorn/internal/objects/Global.java
index db79f5f..9e40dbe 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/Global.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java
@@ -33,11 +33,8 @@
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.util.Arrays;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
@@ -51,7 +48,6 @@
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.GlobalFunctions;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
@@ -59,10 +55,10 @@
import jdk.nashorn.internal.runtime.Scope;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.ScriptingFunctions;
-import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
@@ -73,7 +69,7 @@
* Representation of global scope.
*/
@ScriptClass("Global")
-public final class Global extends ScriptObject implements GlobalObject, Scope {
+public final class Global extends ScriptObject implements Scope {
private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
@@ -229,6 +225,10 @@
@Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
public volatile Object arrayBuffer;
+ /** DataView object */
+ @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
+ public volatile Object dataView;
+
/** TypedArray (int8) */
@Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
public volatile Object int8Array;
@@ -355,6 +355,7 @@
private ScriptObject builtinJavaImporter;
private ScriptObject builtinJavaApi;
private ScriptObject builtinArrayBuffer;
+ private ScriptObject builtinDataView;
private ScriptObject builtinInt8Array;
private ScriptObject builtinUint8Array;
private ScriptObject builtinUint8ClampedArray;
@@ -370,42 +371,9 @@
*/
private ScriptFunction typeErrorThrower;
- private PropertyMap accessorPropertyDescriptorMap;
- private PropertyMap arrayBufferViewMap;
- private PropertyMap dataPropertyDescriptorMap;
- private PropertyMap genericPropertyDescriptorMap;
- private PropertyMap nativeArgumentsMap;
- private PropertyMap nativeArrayMap;
- private PropertyMap nativeArrayBufferMap;
- private PropertyMap nativeBooleanMap;
- private PropertyMap nativeDateMap;
- private PropertyMap nativeErrorMap;
- private PropertyMap nativeEvalErrorMap;
- private PropertyMap nativeJSAdapterMap;
- private PropertyMap nativeJavaImporterMap;
- private PropertyMap nativeNumberMap;
- private PropertyMap nativeRangeErrorMap;
- private PropertyMap nativeReferenceErrorMap;
- private PropertyMap nativeRegExpMap;
- private PropertyMap nativeRegExpExecResultMap;
- private PropertyMap nativeStrictArgumentsMap;
- private PropertyMap nativeStringMap;
- private PropertyMap nativeSyntaxErrorMap;
- private PropertyMap nativeTypeErrorMap;
- private PropertyMap nativeURIErrorMap;
- private PropertyMap prototypeObjectMap;
- private PropertyMap objectMap;
- private PropertyMap functionMap;
- private PropertyMap anonymousFunctionMap;
- private PropertyMap strictFunctionMap;
- private PropertyMap boundFunctionMap;
-
// Flag to indicate that a split method issued a return statement
private int splitState = -1;
- // class cache
- private ClassCache classCache;
-
// Used to store the last RegExp result to support deprecated RegExp constructor properties
private RegExpResult lastRegExpResult;
@@ -456,11 +424,6 @@
super(checkAndGetMap(context));
this.context = context;
this.setIsScope();
-
- final int cacheSize = context.getEnv()._class_cache_size;
- if (cacheSize > 0) {
- classCache = new ClassCache(cacheSize);
- }
}
/**
@@ -469,11 +432,9 @@
* @return the global singleton
*/
public static Global instance() {
- ScriptObject global = Context.getGlobal();
- if (! (global instanceof Global)) {
- throw new IllegalStateException("no current global instance");
- }
- return (Global)global;
+ Global global = Context.getGlobal();
+ global.getClass(); // null check
+ return global;
}
/**
@@ -494,19 +455,30 @@
return instance().getContext();
}
- // GlobalObject interface implementation
+ // Runtime interface to Global
- @Override
+ /**
+ * Is this global of the given Context?
+ * @param ctxt the context
+ * @return true if this global belongs to the given Context
+ */
public boolean isOfContext(final Context ctxt) {
return this.context == ctxt;
}
- @Override
+ /**
+ * Does this global belong to a strict Context?
+ * @return true if this global belongs to a strict Context
+ */
public boolean isStrictContext() {
return context.getEnv()._strict;
}
- @Override
+ /**
+ * Initialize standard builtin objects like "Object", "Array", "Function" etc.
+ * as well as our extension builtin objects like "Java", "JSAdapter" as properties
+ * of the global scope object.
+ */
public void initBuiltinObjects() {
if (this.builtinObject != null) {
// already initialized, just return
@@ -516,12 +488,26 @@
init();
}
- @Override
+ /**
+ * Create a new ScriptFunction object
+ *
+ * @param name function name
+ * @param handle invocation handle for function
+ * @param scope the scope
+ * @param strict are we in strict mode
+ *
+ * @return new script function
+ */
public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
- return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
+ return new ScriptFunctionImpl(name, handle, scope, null, strict ? ScriptFunctionData.IS_STRICT_CONSTRUCTOR : ScriptFunctionData.IS_CONSTRUCTOR);
}
- @Override
+ /**
+ * Wrap a Java object as corresponding script object
+ *
+ * @param obj object to wrap
+ * @return wrapped object
+ */
public Object wrapAsObject(final Object obj) {
if (obj instanceof Boolean) {
return new NativeBoolean((Boolean)obj, this);
@@ -543,7 +529,14 @@
}
}
- @Override
+ /**
+ * Lookup helper for JS primitive types
+ *
+ * @param request the link request for the dynamic call site.
+ * @param self self reference
+ *
+ * @return guarded invocation
+ */
public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
if (self instanceof String || self instanceof ConsString) {
return NativeString.lookupPrimitive(request, self);
@@ -555,12 +548,23 @@
throw new IllegalArgumentException("Unsupported primitive: " + self);
}
- @Override
+ /**
+ * Create a new empty script object
+ *
+ * @return the new ScriptObject
+ */
public ScriptObject newObject() {
- return new JO(getObjectPrototype(), getObjectMap());
+ return new JO(getObjectPrototype(), JO.getInitialMap());
}
- @Override
+ /**
+ * Default value of given type
+ *
+ * @param sobj script object
+ * @param typeHint type hint
+ *
+ * @return default value
+ */
public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
// When the [[DefaultValue]] internal method of O is called with no hint,
// then it behaves as if the hint were Number, unless O is a Date object
@@ -620,7 +624,12 @@
return UNDEFINED;
}
- @Override
+ /**
+ * Is the given ScriptObject an ECMAScript Error object?
+ *
+ * @param sobj the object being checked
+ * @return true if sobj is an Error object
+ */
public boolean isError(final ScriptObject sobj) {
final ScriptObject errorProto = getErrorPrototype();
ScriptObject proto = sobj.getProto();
@@ -633,52 +642,108 @@
return false;
}
- @Override
+ /**
+ * Create a new ECMAScript Error object.
+ *
+ * @param msg error message
+ * @return newly created Error object
+ */
public ScriptObject newError(final String msg) {
return new NativeError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript EvalError object.
+ *
+ * @param msg error message
+ * @return newly created EvalError object
+ */
public ScriptObject newEvalError(final String msg) {
return new NativeEvalError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript RangeError object.
+ *
+ * @param msg error message
+ * @return newly created RangeError object
+ */
public ScriptObject newRangeError(final String msg) {
return new NativeRangeError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript ReferenceError object.
+ *
+ * @param msg error message
+ * @return newly created ReferenceError object
+ */
public ScriptObject newReferenceError(final String msg) {
return new NativeReferenceError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript SyntaxError object.
+ *
+ * @param msg error message
+ * @return newly created SyntaxError object
+ */
public ScriptObject newSyntaxError(final String msg) {
return new NativeSyntaxError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript TypeError object.
+ *
+ * @param msg error message
+ * @return newly created TypeError object
+ */
public ScriptObject newTypeError(final String msg) {
return new NativeTypeError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript URIError object.
+ *
+ * @param msg error message
+ * @return newly created URIError object
+ */
public ScriptObject newURIError(final String msg) {
return new NativeURIError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript GenericDescriptor object.
+ *
+ * @param configurable is the property configurable?
+ * @param enumerable is the property enumerable?
+ * @return newly created GenericDescriptor object
+ */
public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
return new GenericPropertyDescriptor(configurable, enumerable, this);
}
- @Override
+ /**
+ * Create a new ECMAScript DatePropertyDescriptor object.
+ *
+ * @param value of the data property
+ * @param configurable is the property configurable?
+ * @param enumerable is the property enumerable?
+ * @return newly created DataPropertyDescriptor object
+ */
public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
}
- @Override
+ /**
+ * Create a new ECMAScript AccessorPropertyDescriptor object.
+ *
+ * @param get getter function of the user accessor property
+ * @param set setter function of the user accessor property
+ * @param configurable is the property configurable?
+ * @param enumerable is the property enumerable?
+ * @return newly created AccessorPropertyDescriptor object
+ */
public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
@@ -694,62 +759,6 @@
}
- /**
- * Cache for compiled script classes.
- */
- @SuppressWarnings("serial")
- private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
- private final int size;
- private final ReferenceQueue<Class<?>> queue;
-
- ClassCache(int size) {
- super(size, 0.75f, true);
- this.size = size;
- this.queue = new ReferenceQueue<>();
- }
-
- void cache(final Source source, final Class<?> clazz) {
- put(source, new ClassReference(clazz, queue, source));
- }
-
- @Override
- protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
- return size() > size;
- }
-
- @Override
- public ClassReference get(Object key) {
- for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
- remove(ref.source);
- }
- return super.get(key);
- }
-
- }
-
- private static class ClassReference extends SoftReference<Class<?>> {
- private final Source source;
-
- ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
- super(clazz, queue);
- this.source = source;
- }
- }
-
- // Class cache management
- @Override
- public Class<?> findCachedClass(final Source source) {
- assert classCache != null : "Class cache used without being initialized";
- ClassReference ref = classCache.get(source);
- return ref != null ? ref.get() : null;
- }
-
- @Override
- public void cacheClass(final Source source, final Class<?> clazz) {
- assert classCache != null : "Class cache used without being initialized";
- classCache.cache(source, clazz);
- }
-
private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
final T obj = map.get(key);
if (obj != null) {
@@ -767,14 +776,25 @@
private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
- @Override
+
+ /**
+ * Get cached InvokeByName object for the given key
+ * @param key key to be associated with InvokeByName object
+ * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
+ * @return InvokeByName object associated with the key.
+ */
public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
return getLazilyCreatedValue(key, creator, namedInvokers);
}
private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
- @Override
+ /**
+ * Get cached dynamic method handle for the given key
+ * @param key key to be associated with dynamic method handle
+ * @param creator if method handle is absent 'creator' is called to make one (lazy init)
+ * @return dynamic method handle associated with the key.
+ */
public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
return getLazilyCreatedValue(key, creator, dynamicInvokers);
}
@@ -963,6 +983,10 @@
return ScriptFunction.getPrototype(builtinArrayBuffer);
}
+ ScriptObject getDataViewPrototype() {
+ return ScriptFunction.getPrototype(builtinDataView);
+ }
+
ScriptObject getInt8ArrayPrototype() {
return ScriptFunction.getPrototype(builtinInt8Array);
}
@@ -999,123 +1023,6 @@
return ScriptFunction.getPrototype(builtinFloat64Array);
}
- // Builtin PropertyMap accessors
- PropertyMap getAccessorPropertyDescriptorMap() {
- return accessorPropertyDescriptorMap;
- }
-
- PropertyMap getArrayBufferViewMap() {
- return arrayBufferViewMap;
- }
-
- PropertyMap getDataPropertyDescriptorMap() {
- return dataPropertyDescriptorMap;
- }
-
- PropertyMap getGenericPropertyDescriptorMap() {
- return genericPropertyDescriptorMap;
- }
-
- PropertyMap getArgumentsMap() {
- return nativeArgumentsMap;
- }
-
- PropertyMap getArrayMap() {
- return nativeArrayMap;
- }
-
- PropertyMap getArrayBufferMap() {
- return nativeArrayBufferMap;
- }
-
- PropertyMap getBooleanMap() {
- return nativeBooleanMap;
- }
-
- PropertyMap getDateMap() {
- return nativeDateMap;
- }
-
- PropertyMap getErrorMap() {
- return nativeErrorMap;
- }
-
- PropertyMap getEvalErrorMap() {
- return nativeEvalErrorMap;
- }
-
- PropertyMap getJSAdapterMap() {
- return nativeJSAdapterMap;
- }
-
- PropertyMap getJavaImporterMap() {
- return nativeJavaImporterMap;
- }
-
- PropertyMap getNumberMap() {
- return nativeNumberMap;
- }
-
- PropertyMap getRangeErrorMap() {
- return nativeRangeErrorMap;
- }
-
- PropertyMap getReferenceErrorMap() {
- return nativeReferenceErrorMap;
- }
-
- PropertyMap getRegExpMap() {
- return nativeRegExpMap;
- }
-
- PropertyMap getRegExpExecResultMap() {
- return nativeRegExpExecResultMap;
- }
-
- PropertyMap getStrictArgumentsMap() {
- return nativeStrictArgumentsMap;
- }
-
- PropertyMap getStringMap() {
- return nativeStringMap;
- }
-
- PropertyMap getSyntaxErrorMap() {
- return nativeSyntaxErrorMap;
- }
-
- PropertyMap getTypeErrorMap() {
- return nativeTypeErrorMap;
- }
-
- PropertyMap getURIErrorMap() {
- return nativeURIErrorMap;
- }
-
- PropertyMap getPrototypeObjectMap() {
- return prototypeObjectMap;
- }
-
- PropertyMap getObjectMap() {
- return objectMap;
- }
-
- PropertyMap getFunctionMap() {
- return functionMap;
- }
-
- PropertyMap getAnonymousFunctionMap() {
- return anonymousFunctionMap;
- }
-
- PropertyMap getStrictFunctionMap() {
- return strictFunctionMap;
- }
-
- PropertyMap getBoundFunctionMap() {
- return boundFunctionMap;
- }
-
private ScriptFunction getBuiltinArray() {
return builtinArray;
}
@@ -1631,14 +1538,11 @@
final ScriptEnvironment env = getContext().getEnv();
- // duplicate PropertyMaps of Native* classes
- copyInitialMaps(env);
-
// initialize Function and Object constructor
initFunctionAndObject();
// Now fix Global's own proto.
- this.setProto(getObjectPrototype());
+ this.setInitialProto(getObjectPrototype());
// initialize global function properties
this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
@@ -1705,8 +1609,25 @@
initScripting(env);
}
- if (Context.DEBUG && System.getSecurityManager() == null) {
- initDebug();
+ if (Context.DEBUG) {
+ boolean debugOkay;
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
+ debugOkay = true;
+ } catch (final SecurityException ignored) {
+ // if no permission, don't initialize Debug object
+ debugOkay = false;
+ }
+
+ } else {
+ debugOkay = true;
+ }
+
+ if (debugOkay) {
+ initDebug();
+ }
}
copyBuiltins();
@@ -1766,7 +1687,7 @@
final ScriptObject prototype = ScriptFunction.getPrototype(cons);
prototype.set(NativeError.NAME, name, false);
prototype.set(NativeError.MESSAGE, "", false);
- prototype.setProto(errorProto);
+ prototype.setInitialProto(errorProto);
return (ScriptFunction)cons;
}
@@ -1834,6 +1755,7 @@
private void initTypedArray() {
this.builtinArrayBuffer = initConstructor("ArrayBuffer");
+ this.builtinDataView = initConstructor("DataView");
this.builtinInt8Array = initConstructor("Int8Array");
this.builtinUint8Array = initConstructor("Uint8Array");
this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
@@ -1874,6 +1796,7 @@
this.typeError = this.builtinTypeError;
this.uriError = this.builtinURIError;
this.arrayBuffer = this.builtinArrayBuffer;
+ this.dataView = this.builtinDataView;
this.int8Array = this.builtinInt8Array;
this.uint8Array = this.builtinUint8Array;
this.uint8ClampedArray = this.builtinUint8ClampedArray;
@@ -1938,7 +1861,7 @@
}
if (res.getProto() == null) {
- res.setProto(getObjectPrototype());
+ res.setInitialProto(getObjectPrototype());
}
return res;
@@ -1948,46 +1871,6 @@
}
}
- private void copyInitialMaps(final ScriptEnvironment env) {
- this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate();
- this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate();
- this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate();
- this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate();
- this.nativeArrayMap = NativeArray.getInitialMap().duplicate();
- this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate();
- this.nativeDateMap = NativeDate.getInitialMap().duplicate();
- this.nativeErrorMap = NativeError.getInitialMap().duplicate();
- this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate();
- this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate();
- this.nativeNumberMap = NativeNumber.getInitialMap().duplicate();
- this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate();
- this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate();
- this.nativeRegExpMap = NativeRegExp.getInitialMap().duplicate();
- this.nativeRegExpExecResultMap = NativeRegExpExecResult.getInitialMap().duplicate();
- this.nativeStrictArgumentsMap = NativeStrictArguments.getInitialMap().duplicate();
- this.nativeStringMap = NativeString.getInitialMap().duplicate();
- this.nativeSyntaxErrorMap = NativeSyntaxError.getInitialMap().duplicate();
- this.nativeTypeErrorMap = NativeTypeError.getInitialMap().duplicate();
- this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate();
- this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate();
- this.objectMap = JO.getInitialMap().duplicate();
- this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate();
- this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate();
- this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate();
- this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate();
-
- // java
- if (! env._no_java) {
- this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
- }
-
- // typed arrays
- if (! env._no_typed_arrays) {
- this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
- this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
- }
- }
-
// Function and Object constructors are inter-dependent. Also,
// Function.prototype
// functions are not properly initialized. We fix the references here.
@@ -2005,13 +1888,13 @@
// Function.prototype === Object.getPrototypeOf(Function) ===
// <anon-function>
- builtinFunction.setProto(anon);
+ builtinFunction.setInitialProto(anon);
builtinFunction.setPrototype(anon);
anon.set("constructor", builtinFunction, false);
anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
// use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
- this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, false, false, false);
+ this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
typeErrorThrower.setPrototype(UNDEFINED);
// Non-constructor built-in functions do not have "prototype" property
typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
@@ -2021,7 +1904,7 @@
this.builtinObject = (ScriptFunction)initConstructor("Object");
final ScriptObject ObjectPrototype = getObjectPrototype();
// Object.getPrototypeOf(Function.prototype) === Object.prototype
- anon.setProto(ObjectPrototype);
+ anon.setInitialProto(ObjectPrototype);
// Function valued properties of Function.prototype were not properly
// initialized. Because, these were created before global.function and
@@ -2033,10 +1916,10 @@
if (value instanceof ScriptFunction && value != anon) {
final ScriptFunction func = (ScriptFunction)value;
- func.setProto(getFunctionPrototype());
+ func.setInitialProto(getFunctionPrototype());
final ScriptObject prototype = ScriptFunction.getPrototype(func);
if (prototype != null) {
- prototype.setProto(ObjectPrototype);
+ prototype.setInitialProto(ObjectPrototype);
}
}
}
@@ -2051,7 +1934,7 @@
final ScriptFunction func = (ScriptFunction)value;
final ScriptObject prototype = ScriptFunction.getPrototype(func);
if (prototype != null) {
- prototype.setProto(ObjectPrototype);
+ prototype.setInitialProto(ObjectPrototype);
}
}
}
@@ -2069,7 +1952,7 @@
final ScriptFunction func = (ScriptFunction)value;
final ScriptObject prototype = ScriptFunction.getPrototype(func);
if (prototype != null) {
- prototype.setProto(ObjectPrototype);
+ prototype.setInitialProto(ObjectPrototype);
}
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java
index f853573..03f68bf 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java
@@ -68,7 +68,7 @@
final ArrayList<Property> properties = new ArrayList<>(2);
properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH));
properties.add(AccessorProperty.create("callee", Property.NOT_ENUMERABLE, G$CALLEE, S$CALLEE));
- map$ = PropertyMap.newMap(properties).setIsShared();
+ map$ = PropertyMap.newMap(properties);
}
static PropertyMap getInitialMap() {
@@ -267,9 +267,9 @@
final Global global = Global.instance();
final ScriptObject proto = global.getObjectPrototype();
if (isStrict) {
- return new NativeStrictArguments(arguments, numParams, proto, global.getStrictArgumentsMap());
+ return new NativeStrictArguments(arguments, numParams, proto, NativeStrictArguments.getInitialMap());
}
- return new NativeArguments(arguments, callee, numParams, proto, global.getArgumentsMap());
+ return new NativeArguments(arguments, callee, numParams, proto, NativeArguments.getInitialMap());
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
index 67b9f1f..6f07cb9 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
@@ -31,6 +31,7 @@
import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import java.lang.invoke.MethodHandle;
import java.util.ArrayList;
@@ -156,10 +157,6 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
/*
* Constructors.
*/
@@ -208,7 +205,7 @@
}
NativeArray(final ArrayData arrayData, final Global global) {
- super(global.getArrayPrototype(), global.getArrayMap());
+ super(global.getArrayPrototype(), $nasgenmap$);
this.setArray(arrayData);
this.setIsArray();
}
@@ -354,6 +351,27 @@
}
/**
+ * Spec. mentions use of [[DefineOwnProperty]] for indexed properties in
+ * certain places (eg. Array.prototype.map, filter). We can not use ScriptObject.set
+ * method in such cases. This is because set method uses inherited setters (if any)
+ * from any object in proto chain such as Array.prototype, Object.prototype.
+ * This method directly sets a particular element value in the current object.
+ *
+ * @param index key for property
+ * @param value value to define
+ */
+ @Override
+ public final void defineOwnProperty(final int index, final Object value) {
+ assert isValidArrayIndex(index) : "invalid array index";
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ if (longIndex >= getArray().length()) {
+ // make array big enough to hold..
+ setArray(getArray().ensure(longIndex));
+ }
+ setArray(getArray().set(index, value, false));
+ }
+
+ /**
* Return the array contents upcasted as an ObjectArray, regardless of
* representation
*
@@ -371,7 +389,7 @@
* @return true if argument is an array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isArray(final Object self, final Object arg) {
+ public static boolean isArray(final Object self, final Object arg) {
return isArray(arg) || (arg instanceof JSObject && ((JSObject)arg).isArray());
}
@@ -470,7 +488,7 @@
* @return locale specific string representation for array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleString(final Object self) {
+ public static String toLocaleString(final Object self) {
final StringBuilder sb = new StringBuilder();
final Iterator<Object> iter = arrayLikeIterator(self, true);
@@ -516,7 +534,7 @@
* @return the new NativeArray
*/
@Constructor(arity = 1)
- public static Object construct(final boolean newObj, final Object self, final Object... args) {
+ public static NativeArray construct(final boolean newObj, final Object self, final Object... args) {
switch (args.length) {
case 0:
return new NativeArray(0);
@@ -569,7 +587,7 @@
* @return the new NativeArray
*/
@SpecializedConstructor
- public static Object construct(final boolean newObj, final Object self) {
+ public static NativeArray construct(final boolean newObj, final Object self) {
return new NativeArray(0);
}
@@ -584,7 +602,7 @@
* @return the new NativeArray
*/
@SpecializedConstructor
- public static Object construct(final boolean newObj, final Object self, final int length) {
+ public static NativeArray construct(final boolean newObj, final Object self, final int length) {
if (length >= 0) {
return new NativeArray(length);
}
@@ -603,7 +621,7 @@
* @return the new NativeArray
*/
@SpecializedConstructor
- public static Object construct(final boolean newObj, final Object self, final long length) {
+ public static NativeArray construct(final boolean newObj, final Object self, final long length) {
if (length >= 0L && length <= JSType.MAX_UINT) {
return new NativeArray(length);
}
@@ -622,7 +640,7 @@
* @return the new NativeArray
*/
@SpecializedConstructor
- public static Object construct(final boolean newObj, final Object self, final double length) {
+ public static NativeArray construct(final boolean newObj, final Object self, final double length) {
final long uint32length = JSType.toUint32(length);
if (uint32length == length) {
@@ -640,7 +658,7 @@
* @return resulting NativeArray
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object concat(final Object self, final Object... args) {
+ public static NativeArray concat(final Object self, final Object... args) {
final ArrayList<Object> list = new ArrayList<>();
concatToList(list, Global.toObject(self));
@@ -687,7 +705,7 @@
* @return string representation after join
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object join(final Object self, final Object separator) {
+ public static String join(final Object self, final Object separator) {
final StringBuilder sb = new StringBuilder();
final Iterator<Object> iter = arrayLikeIterator(self, true);
final String sep = separator == ScriptRuntime.UNDEFINED ? "," : JSType.toString(separator);
@@ -955,7 +973,7 @@
* @return sorted array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object sort(final Object self, final Object comparefn) {
+ public static ScriptObject sort(final Object self, final Object comparefn) {
try {
final ScriptObject sobj = (ScriptObject) self;
final long len = JSType.toUint32(sobj.getLength());
@@ -1159,7 +1177,7 @@
* @return index of element, or -1 if not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object indexOf(final Object self, final Object searchElement, final Object fromIndex) {
+ public static long indexOf(final Object self, final Object searchElement, final Object fromIndex) {
try {
final ScriptObject sobj = (ScriptObject)Global.toObject(self);
final long len = JSType.toUint32(sobj.getLength());
@@ -1195,7 +1213,7 @@
* @return index of element, or -1 if not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object lastIndexOf(final Object self, final Object... args) {
+ public static long lastIndexOf(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)Global.toObject(self);
final long len = JSType.toUint32(sobj.getLength());
@@ -1230,7 +1248,7 @@
* @return true if callback function return true for every element in the array, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object every(final Object self, final Object callbackfn, final Object thisArg) {
+ public static boolean every(final Object self, final Object callbackfn, final Object thisArg) {
return applyEvery(Global.toObject(self), callbackfn, thisArg);
}
@@ -1254,7 +1272,7 @@
* @return true if callback function returned true for any element in the array, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object some(final Object self, final Object callbackfn, final Object thisArg) {
+ public static boolean some(final Object self, final Object callbackfn, final Object thisArg) {
return new IteratorAction<Boolean>(Global.toObject(self), callbackfn, thisArg, false) {
private final MethodHandle someInvoker = getSOME_CALLBACK_INVOKER();
@@ -1295,7 +1313,7 @@
* @return array with elements transformed by map function
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object map(final Object self, final Object callbackfn, final Object thisArg) {
+ public static NativeArray map(final Object self, final Object callbackfn, final Object thisArg) {
return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) {
private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER();
@@ -1324,7 +1342,7 @@
* @return filtered array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object filter(final Object self, final Object callbackfn, final Object thisArg) {
+ public static NativeArray filter(final Object self, final Object callbackfn, final Object thisArg) {
return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, new NativeArray()) {
private long to = 0;
private final MethodHandle filterInvoker = getFILTER_CALLBACK_INVOKER();
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
index d75a212..70c97da 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.objects;
+import java.nio.ByteBuffer;
import java.util.Arrays;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -43,12 +44,8 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
+ public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) {
if (args.length == 0) {
throw new RuntimeException("missing length argument");
}
@@ -57,7 +54,7 @@
}
protected NativeArrayBuffer(final byte[] byteArray, final Global global) {
- super(global.getArrayBufferPrototype(), global.getArrayBufferMap());
+ super(global.getArrayBufferPrototype(), $nasgenmap$);
this.buffer = byteArray;
}
@@ -84,7 +81,7 @@
}
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object slice(final Object self, final Object begin0, final Object end0) {
+ public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) {
final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
int begin = JSType.toInt32(begin0);
int end = end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : arrayBuffer.getByteLength();
@@ -128,4 +125,16 @@
public int getByteLength() {
return buffer.length;
}
+
+ ByteBuffer getBuffer() {
+ return ByteBuffer.wrap(buffer);
+ }
+
+ ByteBuffer getBuffer(final int offset) {
+ return ByteBuffer.wrap(buffer, offset, buffer.length - offset);
+ }
+
+ ByteBuffer getBuffer(final int offset, final int length) {
+ return ByteBuffer.wrap(buffer, offset, length);
+ }
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java b/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java
index bb57cc7..d645d6d 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java
@@ -30,6 +30,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.objects.annotations.Attribute;
@@ -50,22 +51,21 @@
public final class NativeBoolean extends ScriptObject {
private final boolean value;
- final static MethodHandle WRAPFILTER = findWrapFilter();
+ // Method handle to create an object wrapper for a primitive boolean
+ private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class));
+ // Method handle to retrieve the Boolean prototype object
+ private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeBoolean(final boolean value, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.value = value;
}
NativeBoolean(final boolean flag, final Global global) {
- this(flag, global.getBooleanPrototype(), global.getBooleanMap());
+ this(flag, global.getBooleanPrototype(), $nasgenmap$);
}
NativeBoolean(final boolean flag) {
@@ -110,7 +110,7 @@
* @return string representation of this boolean
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return getBoolean(self).toString();
}
@@ -121,7 +121,7 @@
* @return value of this boolean
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object valueOf(final Object self) {
+ public static boolean valueOf(final Object self) {
return getBoolean(self);
}
@@ -164,7 +164,7 @@
* @return Link to be invoked at call site.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
- return PrimitiveLookup.lookupPrimitive(request, Boolean.class, new NativeBoolean((Boolean)receiver), WRAPFILTER);
+ return PrimitiveLookup.lookupPrimitive(request, Boolean.class, new NativeBoolean((Boolean)receiver), WRAPFILTER, PROTOFILTER);
}
/**
@@ -178,7 +178,12 @@
return new NativeBoolean((Boolean)receiver);
}
- private static MethodHandle findWrapFilter() {
- return MH.findStatic(MethodHandles.lookup(), NativeBoolean.class, "wrapFilter", MH.type(NativeBoolean.class, Object.class));
+ @SuppressWarnings("unused")
+ private static Object protoFilter(final Object object) {
+ return Global.instance().getBooleanPrototype();
+ }
+
+ private static MethodHandle findOwnMH(final String name, final MethodType type) {
+ return MH.findStatic(MethodHandles.lookup(), NativeBoolean.class, name, type);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java
new file mode 100644
index 0000000..414ff8ae
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (c) 2014, 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 jdk.nashorn.internal.objects;
+
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import jdk.nashorn.internal.objects.annotations.Attribute;
+import jdk.nashorn.internal.objects.annotations.Constructor;
+import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
+import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * <p>
+ * DataView builtin constructor. Based on the specification here:
+ * http://www.khronos.org/registry/typedarray/specs/latest/#8
+ * </p>
+ * <p>
+ * An ArrayBuffer is a useful object for representing an arbitrary chunk of data.
+ * In many cases, such data will be read from disk or from the network, and will
+ * not follow the alignment restrictions that are imposed on the typed array views
+ * described earlier. In addition, the data will often be heterogeneous in nature
+ * and have a defined byte order. The DataView view provides a low-level interface
+ * for reading such data from and writing it to an ArrayBuffer.
+ * </p>
+ * <p>
+ * Regardless of the host computer's endianness, DataView reads or writes values
+ * to or from main memory with a specified endianness: big or little.
+ * </p>
+ */
+@ScriptClass("DataView")
+public class NativeDataView extends ScriptObject {
+ // initialized by nasgen
+ private static PropertyMap $nasgenmap$;
+
+ // inherited ArrayBufferView properties
+
+ /**
+ * Underlying ArrayBuffer storage object
+ */
+ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
+ public final Object buffer;
+
+ /**
+ * The offset in bytes from the start of the ArrayBuffer
+ */
+ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
+ public final int byteOffset;
+
+ /**
+ * The number of bytes from the offset that this DataView will reference
+ */
+ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
+ public final int byteLength;
+
+ // underlying ByteBuffer
+ private final ByteBuffer buf;
+
+ private NativeDataView(NativeArrayBuffer arrBuf) {
+ this(arrBuf, arrBuf.getBuffer(), 0);
+ }
+
+ private NativeDataView(NativeArrayBuffer arrBuf, int offset) {
+ this(arrBuf, bufferFrom(arrBuf, offset), offset);
+ }
+
+ private NativeDataView(NativeArrayBuffer arrBuf, int offset, int length) {
+ this(arrBuf, bufferFrom(arrBuf, offset, length), offset, length);
+ }
+
+ private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset) {
+ this(arrBuf, buf, offset, buf.capacity() - offset);
+ }
+
+ private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset, final int length) {
+ super(Global.instance().getDataViewPrototype(), $nasgenmap$);
+ this.buffer = arrBuf;
+ this.byteOffset = offset;
+ this.byteLength = length;
+ this.buf = buf;
+ }
+
+ /**
+ * Create a new DataView object using the passed ArrayBuffer for its
+ * storage. Optional byteOffset and byteLength can be used to limit the
+ * section of the buffer referenced. The byteOffset indicates the offset in
+ * bytes from the start of the ArrayBuffer, and the byteLength is the number
+ * of bytes from the offset that this DataView will reference. If both
+ * byteOffset and byteLength are omitted, the DataView spans the entire
+ * ArrayBuffer range. If the byteLength is omitted, the DataView extends from
+ * the given byteOffset until the end of the ArrayBuffer.
+ *
+ * If the given byteOffset and byteLength references an area beyond the end
+ * of the ArrayBuffer an exception is raised.
+
+ * @param newObj if this constructor was invoked with 'new' or not
+ * @param self constructor function object
+ * @param args arguments to the constructor
+ * @return newly constructed DataView object
+ */
+ @Constructor(arity = 1)
+ public static NativeDataView constructor(final boolean newObj, final Object self, final Object... args) {
+ if (args.length == 0 || !(args[0] instanceof NativeArrayBuffer)) {
+ throw typeError("not.an.arraybuffer.in.dataview");
+ }
+
+ final NativeArrayBuffer arrBuf = (NativeArrayBuffer) args[0];
+ switch (args.length) {
+ case 1:
+ return new NativeDataView(arrBuf);
+ case 2:
+ return new NativeDataView(arrBuf, JSType.toInt32(args[1]));
+ default:
+ return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2]));
+ }
+ }
+
+ /**
+ * Specialized version of DataView constructor
+ *
+ * @param newObj if this constructor was invoked with 'new' or not
+ * @param self constructor function object
+ * @param arrBuf underlying ArrayBuffer storage object
+ * @param offset offset in bytes from the start of the ArrayBuffer
+ * @return newly constructed DataView object
+ */
+ @SpecializedConstructor
+ public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) {
+ if (!(arrBuf instanceof NativeArrayBuffer)) {
+ throw typeError("not.an.arraybuffer.in.dataview");
+ }
+ return new NativeDataView((NativeArrayBuffer) arrBuf, offset);
+ }
+
+ /**
+ * Specialized version of DataView constructor
+ *
+ * @param newObj if this constructor was invoked with 'new' or not
+ * @param self constructor function object
+ * @param arrBuf underlying ArrayBuffer storage object
+ * @param offset in bytes from the start of the ArrayBuffer
+ * @param length is the number of bytes from the offset that this DataView will reference
+ * @return newly constructed DataView object
+ */
+ @SpecializedConstructor
+ public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) {
+ if (!(arrBuf instanceof NativeArrayBuffer)) {
+ throw typeError("not.an.arraybuffer.in.dataview");
+ }
+ return new NativeDataView((NativeArrayBuffer) arrBuf, offset, length);
+ }
+
+ // Gets the value of the given type at the specified byte offset
+ // from the start of the view. There is no alignment constraint;
+ // multi-byte values may be fetched from any offset.
+ //
+ // For multi-byte values, the optional littleEndian argument
+ // indicates whether a big-endian or little-endian value should be
+ // read. If false or undefined, a big-endian value is read.
+ //
+ // These methods raise an exception if they would read
+ // beyond the end of the view.
+
+ /**
+ * Get 8-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 8-bit signed int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE)
+ public static int getInt8(final Object self, final Object byteOffset) {
+ try {
+ return getBuffer(self).get(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 8-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 8-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt8(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self).get(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 8-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 8-bit unsigned int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE)
+ public static int getUint8(final Object self, final Object byteOffset) {
+ try {
+ return (0xFF & getBuffer(self).get(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 8-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 8-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getUint8(final Object self, final int byteOffset) {
+ try {
+ return (0xFF & getBuffer(self).get(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 16-bit signed int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static int getInt16(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 16-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt16(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self, false).getShort(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 16-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt16(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getShort(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 16-bit unsigned int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static int getUint16(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 16-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getUint16(final Object self, final int byteOffset) {
+ try {
+ return (int) (0xFFFF & getBuffer(self, false).getShort(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 16-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getUint16(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit signed int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static int getInt32(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 32-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt32(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self, false).getInt(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt32(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getInt(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit unsigned int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static long getUint32(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 32-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static long getUint32(final Object self, final int byteOffset) {
+ try {
+ return (long) (0xFFFFFFFFL & getBuffer(self, false).getInt(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit float value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static double getFloat32(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getFloat(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 32-bit float value at the byteOffset
+ */
+ @SpecializedFunction
+ public static double getFloat32(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self, false).getFloat(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit float value at the byteOffset
+ */
+ @SpecializedFunction
+ public static double getFloat32(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getFloat(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 64-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 64-bit float value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static double getFloat64(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getDouble(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 64-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 64-bit float value at the byteOffset
+ */
+ @SpecializedFunction
+ public static double getFloat64(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self, false).getDouble(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 64-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 64-bit float value at the byteOffset
+ */
+ @SpecializedFunction
+ public static double getFloat64(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getDouble(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ // Stores a value of the given type at the specified byte offset
+ // from the start of the view. There is no alignment constraint;
+ // multi-byte values may be stored at any offset.
+ //
+ // For multi-byte values, the optional littleEndian argument
+ // indicates whether the value should be stored in big-endian or
+ // little-endian byte order. If false or undefined, the value is
+ // stored in big-endian byte order.
+ //
+ // These methods raise an exception if they would write
+ // beyond the end of the view.
+
+ /**
+ * Set 8-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param value byte value to set
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setInt8(final Object self, final Object byteOffset, final Object value) {
+ try {
+ getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 8-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param value byte value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt8(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self).put(byteOffset, (byte)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 8-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value byte value to set
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setUint8(final Object self, final Object byteOffset, final Object value) {
+ try {
+ getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 8-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value byte value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint8(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self).put(byteOffset, (byte)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setInt16(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt16(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self, false).putShort(byteOffset, (short)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt16(final Object self, final int byteOffset, final int value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setUint16(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint16(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self, false).putShort(byteOffset, (short)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint16(final Object self, final int byteOffset, final int value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setInt32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt32(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self, false).putInt(byteOffset, value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt32(final Object self, final int byteOffset, final int value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putInt(byteOffset, value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setUint32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toUint32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint32(final Object self, final int byteOffset, final long value) {
+ try {
+ getBuffer(self, false).putInt(byteOffset, (int)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint32(final Object self, final int byteOffset, final long value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putInt(byteOffset, (int)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value float value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setFloat32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putFloat((int)JSType.toUint32(byteOffset), (float)JSType.toNumber(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value float value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setFloat32(final Object self, final int byteOffset, final double value) {
+ try {
+ getBuffer(self, false).putFloat(byteOffset, (float)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value float value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setFloat32(final Object self, final int byteOffset, final double value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putFloat(byteOffset, (float)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 64-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value double value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setFloat64(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putDouble((int)JSType.toUint32(byteOffset), JSType.toNumber(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 64-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value double value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setFloat64(final Object self, final int byteOffset, final double value) {
+ try {
+ getBuffer(self, false).putDouble(byteOffset, value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 64-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value double value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setFloat64(final Object self, final int byteOffset, final double value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putDouble(byteOffset, value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ // internals only below this point
+ private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset) {
+ try {
+ return nab.getBuffer(offset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.constructor.offset");
+ }
+ }
+
+ private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset, final int length) {
+ try {
+ return nab.getBuffer(offset, length);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.constructor.offset");
+ }
+ }
+
+ private static NativeDataView checkSelf(final Object self) {
+ if (!(self instanceof NativeDataView)) {
+ throw typeError("not.an.arraybuffer", ScriptRuntime.safeToString(self));
+ }
+ return (NativeDataView)self;
+ }
+
+ private static ByteBuffer getBuffer(final Object self) {
+ return checkSelf(self).buf;
+ }
+
+ private static ByteBuffer getBuffer(final Object self, final Object littleEndian) {
+ return getBuffer(self, JSType.toBoolean(littleEndian));
+ }
+
+ private static ByteBuffer getBuffer(final Object self, final boolean littleEndian) {
+ return getBuffer(self).order(littleEndian? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+ }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
index 935285f..b3661df 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
@@ -114,10 +114,6 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeDate(final double time, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
final ScriptEnvironment env = Global.getEnv();
@@ -127,7 +123,7 @@
}
NativeDate(final double time, final Global global) {
- this(time, global.getDatePrototype(), global.getDateMap());
+ this(time, global.getDatePrototype(), $nasgenmap$);
}
private NativeDate (final double time) {
@@ -230,7 +226,7 @@
* @return Date interpreted from the string, or NaN for illegal values
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object parse(final Object self, final Object string) {
+ public static double parse(final Object self, final Object string) {
return parseDateString(JSType.toString(string));
}
@@ -242,7 +238,7 @@
* @return a time clip according to the ECMA specification
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 7, where = Where.CONSTRUCTOR)
- public static Object UTC(final Object self, final Object... args) {
+ public static double UTC(final Object self, final Object... args) {
final NativeDate nd = new NativeDate(0);
final double[] d = convertCtorArgs(args);
final double time = d == null ? Double.NaN : timeClip(makeDate(d));
@@ -257,8 +253,8 @@
* @return a Date that points to the current moment in time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object now(final Object self) {
- return (double)System.currentTimeMillis();
+ public static long now(final Object self) {
+ return System.currentTimeMillis();
}
/**
@@ -268,7 +264,7 @@
* @return string value that represents the Date in the current time zone
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return toStringImpl(self, FORMAT_DATE_TIME);
}
@@ -279,7 +275,7 @@
* @return string value with the "date" part of the Date in the current time zone
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toDateString(final Object self) {
+ public static String toDateString(final Object self) {
return toStringImpl(self, FORMAT_DATE);
}
@@ -290,7 +286,7 @@
* @return string value with "time" part of Date in the current time zone
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toTimeString(final Object self) {
+ public static String toTimeString(final Object self) {
return toStringImpl(self, FORMAT_TIME);
}
@@ -301,7 +297,7 @@
* @return string value that represents the Data in the current time zone and locale
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleString(final Object self) {
+ public static String toLocaleString(final Object self) {
return toStringImpl(self, FORMAT_LOCAL_DATE_TIME);
}
@@ -312,7 +308,7 @@
* @return string value with the "date" part of the Date in the current time zone and locale
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleDateString(final Object self) {
+ public static String toLocaleDateString(final Object self) {
return toStringImpl(self, FORMAT_LOCAL_DATE);
}
@@ -323,7 +319,7 @@
* @return string value with the "time" part of Date in the current time zone and locale
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleTimeString(final Object self) {
+ public static String toLocaleTimeString(final Object self) {
return toStringImpl(self, FORMAT_LOCAL_TIME);
}
@@ -334,7 +330,7 @@
* @return valueOf - a number which is this time value
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object valueOf(final Object self) {
+ public static double valueOf(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null) ? nd.getTime() : Double.NaN;
}
@@ -346,7 +342,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getTime(final Object self) {
+ public static double getTime(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null) ? nd.getTime() : Double.NaN;
}
@@ -369,7 +365,7 @@
* @return UTC full year
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCFullYear(final Object self) {
+ public static double getUTCFullYear(final Object self) {
return getUTCField(self, YEAR);
}
@@ -380,7 +376,7 @@
* @return year
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getYear(final Object self) {
+ public static double getYear(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null && nd.isValidDate()) ? (yearFromTime(nd.getLocalTime()) - 1900) : Double.NaN;
}
@@ -392,7 +388,7 @@
* @return month
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getMonth(final Object self) {
+ public static double getMonth(final Object self) {
return getField(self, MONTH);
}
@@ -403,7 +399,7 @@
* @return UTC month
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCMonth(final Object self) {
+ public static double getUTCMonth(final Object self) {
return getUTCField(self, MONTH);
}
@@ -414,7 +410,7 @@
* @return date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getDate(final Object self) {
+ public static double getDate(final Object self) {
return getField(self, DAY);
}
@@ -425,7 +421,7 @@
* @return UTC Date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCDate(final Object self) {
+ public static double getUTCDate(final Object self) {
return getUTCField(self, DAY);
}
@@ -436,7 +432,7 @@
* @return day
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getDay(final Object self) {
+ public static double getDay(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null && nd.isValidDate()) ? weekDay(nd.getLocalTime()) : Double.NaN;
}
@@ -448,7 +444,7 @@
* @return UTC day
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCDay(final Object self) {
+ public static double getUTCDay(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null && nd.isValidDate()) ? weekDay(nd.getTime()) : Double.NaN;
}
@@ -460,7 +456,7 @@
* @return hours
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getHours(final Object self) {
+ public static double getHours(final Object self) {
return getField(self, HOUR);
}
@@ -471,7 +467,7 @@
* @return UTC hours
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCHours(final Object self) {
+ public static double getUTCHours(final Object self) {
return getUTCField(self, HOUR);
}
@@ -482,7 +478,7 @@
* @return minutes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getMinutes(final Object self) {
+ public static double getMinutes(final Object self) {
return getField(self, MINUTE);
}
@@ -493,7 +489,7 @@
* @return UTC minutes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCMinutes(final Object self) {
+ public static double getUTCMinutes(final Object self) {
return getUTCField(self, MINUTE);
}
@@ -504,7 +500,7 @@
* @return seconds
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getSeconds(final Object self) {
+ public static double getSeconds(final Object self) {
return getField(self, SECOND);
}
@@ -515,7 +511,7 @@
* @return UTC seconds
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCSeconds(final Object self) {
+ public static double getUTCSeconds(final Object self) {
return getUTCField(self, SECOND);
}
@@ -526,7 +522,7 @@
* @return milliseconds
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getMilliseconds(final Object self) {
+ public static double getMilliseconds(final Object self) {
return getField(self, MILLISECOND);
}
@@ -537,7 +533,7 @@
* @return UTC milliseconds
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCMilliseconds(final Object self) {
+ public static double getUTCMilliseconds(final Object self) {
return getUTCField(self, MILLISECOND);
}
@@ -548,7 +544,7 @@
* @return time zone offset or NaN if N/A
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getTimezoneOffset(final Object self) {
+ public static double getTimezoneOffset(final Object self) {
final NativeDate nd = getNativeDate(self);
if (nd != null && nd.isValidDate()) {
final long msec = (long) nd.getTime();
@@ -565,7 +561,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object setTime(final Object self, final Object time) {
+ public static double setTime(final Object self, final Object time) {
final NativeDate nd = getNativeDate(self);
final double num = timeClip(JSType.toNumber(time));
nd.setTime(num);
@@ -580,7 +576,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object setMilliseconds(final Object self, final Object... args) {
+ public static double setMilliseconds(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MILLISECOND, args, true);
return nd.getTime();
@@ -594,7 +590,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object setUTCMilliseconds(final Object self, final Object... args) {
+ public static double setUTCMilliseconds(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MILLISECOND, args, false);
return nd.getTime();
@@ -608,7 +604,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static Object setSeconds(final Object self, final Object... args) {
+ public static double setSeconds(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, SECOND, args, true);
return nd.getTime();
@@ -622,7 +618,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static Object setUTCSeconds(final Object self, final Object... args) {
+ public static double setUTCSeconds(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, SECOND, args, false);
return nd.getTime();
@@ -636,7 +632,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static Object setMinutes(final Object self, final Object... args) {
+ public static double setMinutes(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MINUTE, args, true);
return nd.getTime();
@@ -650,7 +646,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static Object setUTCMinutes(final Object self, final Object... args) {
+ public static double setUTCMinutes(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MINUTE, args, false);
return nd.getTime();
@@ -664,7 +660,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
- public static Object setHours(final Object self, final Object... args) {
+ public static double setHours(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, HOUR, args, true);
return nd.getTime();
@@ -678,7 +674,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
- public static Object setUTCHours(final Object self, final Object... args) {
+ public static double setUTCHours(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, HOUR, args, false);
return nd.getTime();
@@ -692,7 +688,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object setDate(final Object self, final Object... args) {
+ public static double setDate(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, DAY, args, true);
return nd.getTime();
@@ -706,7 +702,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object setUTCDate(final Object self, final Object... args) {
+ public static double setUTCDate(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, DAY, args, false);
return nd.getTime();
@@ -720,7 +716,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static Object setMonth(final Object self, final Object... args) {
+ public static double setMonth(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MONTH, args, true);
return nd.getTime();
@@ -734,7 +730,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static Object setUTCMonth(final Object self, final Object... args) {
+ public static double setUTCMonth(final Object self, final Object... args) {
final NativeDate nd = ensureNativeDate(self);
setFields(nd, MONTH, args, false);
return nd.getTime();
@@ -748,7 +744,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static Object setFullYear(final Object self, final Object... args) {
+ public static double setFullYear(final Object self, final Object... args) {
final NativeDate nd = ensureNativeDate(self);
if (nd.isValidDate()) {
setFields(nd, YEAR, args, true);
@@ -771,7 +767,7 @@
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static Object setUTCFullYear(final Object self, final Object... args) {
+ public static double setUTCFullYear(final Object self, final Object... args) {
final NativeDate nd = ensureNativeDate(self);
if (nd.isValidDate()) {
setFields(nd, YEAR, args, false);
@@ -790,7 +786,7 @@
* @return NativeDate
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object setYear(final Object self, final Object year) {
+ public static double setYear(final Object self, final Object year) {
final NativeDate nd = getNativeDate(self);
if (isNaN(nd.getTime())) {
nd.setTime(utc(0, nd.getTimeZone()));
@@ -817,7 +813,7 @@
* @return string representation of date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toUTCString(final Object self) {
+ public static String toUTCString(final Object self) {
return toGMTStringImpl(self);
}
@@ -830,7 +826,7 @@
* @return string representation of date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toGMTString(final Object self) {
+ public static String toGMTString(final Object self) {
return toGMTStringImpl(self);
}
@@ -841,7 +837,7 @@
* @return string representation of date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toISOString(final Object self) {
+ public static String toISOString(final Object self) {
return toISOStringImpl(self);
}
@@ -1286,14 +1282,14 @@
}
}
- private static Object getField(final Object self, final int field) {
+ private static double getField(final Object self, final int field) {
final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? valueFromTime(field, nd.getLocalTime()) : Double.NaN;
+ return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getLocalTime()) : Double.NaN;
}
- private static Object getUTCField(final Object self, final int field) {
+ private static double getUTCField(final Object self, final int field) {
final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? valueFromTime(field, nd.getTime()) : Double.NaN;
+ return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getTime()) : Double.NaN;
}
private static void setFields(final NativeDate nd, final int fieldId, final Object[] args, final boolean local) {
@@ -1348,5 +1344,4 @@
private TimeZone getTimeZone() {
return timezone;
}
-
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java
index 9ee7c99..5d80c37 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java
@@ -34,7 +34,7 @@
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.PropertyListenerManager;
+import jdk.nashorn.internal.runtime.PropertyListeners;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -116,7 +116,7 @@
* @return true if reference identity
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object identical(final Object self, final Object obj1, final Object obj2) {
+ public static boolean identical(final Object self, final Object obj1, final Object obj2) {
return obj1 == obj2;
}
@@ -144,7 +144,7 @@
* @return return {@link Object#equals(Object)} for objects.
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object equals(final Object self, final Object obj1, final Object obj2) {
+ public static boolean equals(final Object self, final Object obj1, final Object obj2) {
return Objects.equals(obj1, obj2);
}
@@ -156,7 +156,7 @@
* @return Java string representation of {@code obj}
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object toJavaString(final Object self, final Object obj) {
+ public static String toJavaString(final Object self, final Object obj) {
return Objects.toString(obj);
}
@@ -168,7 +168,7 @@
* @return string representation
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object toIdentString(final Object self, final Object obj) {
+ public static String toIdentString(final Object self, final Object obj) {
if (obj == null) {
return "null";
}
@@ -185,8 +185,8 @@
* @return listener count
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object getListenerCount(final Object self, final Object obj) {
- return (obj instanceof ScriptObject)? ((ScriptObject)obj).getListenerCount() : 0;
+ public static int getListenerCount(final Object self, final Object obj) {
+ return (obj instanceof ScriptObject) ? PropertyListeners.getListenerCount((ScriptObject) obj) : 0;
}
/**
@@ -203,14 +203,13 @@
out.println("ScriptObject count " + ScriptObject.getCount());
out.println("Scope count " + ScriptObject.getScopeCount());
- out.println("ScriptObject listeners added " + PropertyListenerManager.getListenersAdded());
- out.println("ScriptObject listeners removed " + PropertyListenerManager.getListenersRemoved());
+ out.println("ScriptObject listeners added " + PropertyListeners.getListenersAdded());
+ out.println("ScriptObject listeners removed " + PropertyListeners.getListenersRemoved());
out.println("ScriptFunction constructor calls " + ScriptFunction.getConstructorCount());
out.println("ScriptFunction invokes " + ScriptFunction.getInvokes());
out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
out.println("PropertyMap count " + PropertyMap.getCount());
out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
- out.println("PropertyMap shared " + PropertyMap.getSharedCount());
out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java
index d3e2eff..1b6b809 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java
@@ -38,7 +38,6 @@
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
-import jdk.nashorn.internal.objects.ScriptFunctionImpl;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -75,7 +74,7 @@
static final String FILENAME = "__fileName__";
/** Message property name */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** ECMA 15.11.4.2 Error.prototype.name */
@@ -86,13 +85,14 @@
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
private NativeError(final Object msg, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
if (msg != UNDEFINED) {
@@ -100,10 +100,11 @@
} else {
this.delete(NativeError.MESSAGE, false);
}
+ initException(this);
}
NativeError(final Object msg, final Global global) {
- this(msg, global.getErrorPrototype(), global.getErrorMap());
+ this(msg, global.getErrorPrototype(), $nasgenmap$);
}
private NativeError(final Object msg) {
@@ -125,10 +126,18 @@
* @return NativeError instance
*/
@Constructor
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeError(msg);
}
+ // This is called NativeError, NativeTypeError etc. to
+ // associate a ECMAException with the ECMA Error object.
+ @SuppressWarnings("unused")
+ static void initException(final ScriptObject self) {
+ // ECMAException constructor has side effects
+ new ECMAException(self, null);
+ }
+
/**
* Nashorn extension: Error.captureStackTrace. Capture stack trace at the point of call into the Error object provided.
*
@@ -136,16 +145,17 @@
* @param errorObj the error object
* @return undefined
*/
- @SuppressWarnings("unused")
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object captureStackTrace(final Object self, final Object errorObj) {
Global.checkObject(errorObj);
final ScriptObject sobj = (ScriptObject)errorObj;
- new ECMAException(sobj, null); //constructor has side effects
- sobj.delete("stack", false);
- final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK);
- final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK);
- sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
+ initException(sobj);
+ sobj.delete(STACK, false);
+ if (! sobj.has("stack")) {
+ final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK);
+ final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK);
+ sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
+ }
return UNDEFINED;
}
@@ -226,7 +236,11 @@
public static Object setLineNumber(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(LINENUMBER, value, false);
+ if (sobj.hasOwnProperty(LINENUMBER)) {
+ sobj.put(LINENUMBER, value, false);
+ } else {
+ sobj.addOwnProperty(LINENUMBER, Attribute.NOT_ENUMERABLE, value);
+ }
return value;
}
@@ -254,7 +268,11 @@
public static Object setColumnNumber(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(COLUMNNUMBER, value, false);
+ if (sobj.hasOwnProperty(COLUMNNUMBER)) {
+ sobj.put(COLUMNNUMBER, value, false);
+ } else {
+ sobj.addOwnProperty(COLUMNNUMBER, Attribute.NOT_ENUMERABLE, value);
+ }
return value;
}
@@ -282,7 +300,11 @@
public static Object setFileName(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(FILENAME, value, false);
+ if (sobj.hasOwnProperty(FILENAME)) {
+ sobj.put(FILENAME, value, false);
+ } else {
+ sobj.addOwnProperty(FILENAME, Attribute.NOT_ENUMERABLE, value);
+ }
return value;
}
@@ -304,10 +326,12 @@
final Object exception = ECMAException.getException(sobj);
if (exception instanceof Throwable) {
- return getScriptStackString(sobj, (Throwable)exception);
+ Object value = getScriptStackString(sobj, (Throwable)exception);
+ sobj.put(STACK, value, false);
+ return value;
}
- return "";
+ return UNDEFINED;
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java
index 89e9485..586c7cf 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java
@@ -44,7 +44,7 @@
public final class NativeEvalError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,13 +55,14 @@
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
private NativeEvalError(final Object msg, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
if (msg != UNDEFINED) {
@@ -69,10 +70,11 @@
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
NativeEvalError(final Object msg, final Global global) {
- this(msg, global.getEvalErrorPrototype(), global.getEvalErrorMap());
+ this(msg, global.getEvalErrorPrototype(), $nasgenmap$);
}
private NativeEvalError(final Object msg) {
@@ -96,7 +98,7 @@
* @return new EvalError
*/
@Constructor(name = "EvalError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeEvalError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeEvalError(msg);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
index b96c81c..a9dfb7a 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
@@ -136,8 +136,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeFloat32Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeFloat32Array)constructorImpl(args, FACTORY);
}
NativeFloat32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -192,8 +192,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeFloat32Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeFloat32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
index af9251f..61b5880 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
@@ -146,8 +146,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeFloat64Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeFloat64Array)constructorImpl(args, FACTORY);
}
NativeFloat64Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -202,8 +202,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeFloat64Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeFloat64Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java
index d092cfb..3d45cc1 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java
@@ -71,7 +71,7 @@
* @return string representation of Function
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
if (!(self instanceof ScriptFunction)) {
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
}
@@ -174,7 +174,7 @@
* @return function with bound arguments
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object bind(final Object self, final Object... args) {
+ public static ScriptFunction bind(final Object self, final Object... args) {
if (!(self instanceof ScriptFunction)) {
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
}
@@ -199,7 +199,7 @@
* @return source for function
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toSource(final Object self) {
+ public static String toSource(final Object self) {
if (!(self instanceof ScriptFunction)) {
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
}
@@ -217,7 +217,7 @@
* @return new NativeFunction
*/
@Constructor(arity = 1)
- public static Object function(final boolean newObj, final Object self, final Object... args) {
+ public static ScriptFunction function(final boolean newObj, final Object self, final Object... args) {
final StringBuilder sb = new StringBuilder();
sb.append("(function (");
@@ -253,7 +253,7 @@
final Global global = Global.instance();
- return Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
+ return (ScriptFunction)Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
}
private static void checkFunctionParameters(final String params) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
index e24691a..f6aa205 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
@@ -100,8 +100,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeInt16Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeInt16Array)constructorImpl(args, FACTORY);
}
NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength) {
@@ -151,8 +151,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeInt16Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeInt16Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
index b25f849..643bd81 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
@@ -103,8 +103,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeInt32Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeInt32Array)constructorImpl(args, FACTORY);
}
NativeInt32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -154,8 +154,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeInt32Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeInt32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
index e506910..5822c6d 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
@@ -93,8 +93,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeInt8Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeInt8Array)constructorImpl(args, FACTORY);
}
NativeInt8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -144,8 +144,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeInt8Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeInt8Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
index 668ca8c..84036a3 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
@@ -146,10 +146,6 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
NativeJSAdapter(final Object overrides, final ScriptObject adaptee, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.adaptee = wrapAdaptee(adaptee);
@@ -163,7 +159,7 @@
}
private static ScriptObject wrapAdaptee(final ScriptObject adaptee) {
- return new JO(adaptee, Global.instance().getObjectMap());
+ return new JO(adaptee, JO.getInitialMap());
}
@Override
@@ -540,7 +536,7 @@
* @return new NativeJSAdapter
*/
@Constructor
- public static Object construct(final boolean isNew, final Object self, final Object... args) {
+ public static NativeJSAdapter construct(final boolean isNew, final Object self, final Object... args) {
Object proto = UNDEFINED;
Object overrides = UNDEFINED;
Object adaptee;
@@ -577,7 +573,7 @@
proto = global.getJSAdapterPrototype();
}
- return new NativeJSAdapter(overrides, (ScriptObject)adaptee, (ScriptObject)proto, global.getJSAdapterMap());
+ return new NativeJSAdapter(overrides, (ScriptObject)adaptee, (ScriptObject)proto, $nasgenmap$);
}
@Override
@@ -622,14 +618,14 @@
case "getMethod":
final FindProperty find = adaptee.findProperty(__call__, true);
if (find != null) {
- final Object value = getObjectValue(find);
+ final Object value = find.getObjectValue();
if (value instanceof ScriptFunction) {
final ScriptFunctionImpl func = (ScriptFunctionImpl)value;
// TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
// to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
- adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__),
+ adaptee.getProtoSwitchPoint(__call__, find.getOwner()),
testJSAdaptor(adaptee, null, null, null));
}
}
@@ -691,7 +687,7 @@
final MethodType type = desc.getMethodType();
if (findData != null) {
final String name = desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null;
- final Object value = getObjectValue(findData);
+ final Object value = findData.getObjectValue();
if (value instanceof ScriptFunction) {
final ScriptFunction func = (ScriptFunction)value;
@@ -700,7 +696,7 @@
if (methodHandle != null) {
return new GuardedInvocation(
methodHandle,
- adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
+ adaptee.getProtoSwitchPoint(hook, findData.getOwner()),
testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
}
}
@@ -713,7 +709,7 @@
final MethodHandle methodHandle = hook.equals(__put__) ?
MH.asType(Lookup.EMPTY_SETTER, type) :
Lookup.emptyGetter(type.returnType());
- return new GuardedInvocation(methodHandle, adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), testJSAdaptor(adaptee, null, null, null));
+ return new GuardedInvocation(methodHandle, adaptee.getProtoSwitchPoint(hook, null), testJSAdaptor(adaptee, null, null, null));
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
index b863e24f..7879bab 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
@@ -75,7 +75,7 @@
* @see #type(Object, Object)
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isType(final Object self, final Object type) {
+ public static boolean isType(final Object self, final Object type) {
return type instanceof StaticClass;
}
@@ -338,7 +338,7 @@
* null.
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object from(final Object self, final Object objArray) {
+ public static NativeArray from(final Object self, final Object objArray) {
if (objArray == null) {
return null;
} else if (objArray instanceof Collection) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
index 3e46a2c..40ecbff 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
@@ -60,17 +60,13 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeJavaImporter(final Object[] args, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.args = args;
}
private NativeJavaImporter(final Object[] args, final Global global) {
- this(args, global.getJavaImporterPrototype(), global.getJavaImporterMap());
+ this(args, global.getJavaImporterPrototype(), $nasgenmap$);
}
private NativeJavaImporter(final Object[] args) {
@@ -90,7 +86,7 @@
* @return NativeJavaImporter instance
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean isNew, final Object self, final Object... args) {
+ public static NativeJavaImporter constructor(final boolean isNew, final Object self, final Object... args) {
return new NativeJavaImporter(args);
}
@@ -134,6 +130,11 @@
return createAndSetProperty(desc) ? super.lookup(desc, request) : super.noSuchMethod(desc, request);
}
+ @Override
+ protected Object invokeNoSuchProperty(final String name) {
+ return createProperty(name);
+ }
+
private boolean createAndSetProperty(final CallSiteDescriptor desc) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final Object value = createProperty(name);
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java b/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java
index cc50fbb..ec53965 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java
@@ -92,7 +92,7 @@
* @return abs of value
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object abs(final Object self, final Object x) {
+ public static double abs(final Object self, final Object x) {
return Math.abs(JSType.toNumber(x));
}
@@ -144,7 +144,7 @@
* @return acos of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object acos(final Object self, final Object x) {
+ public static double acos(final Object self, final Object x) {
return Math.acos(JSType.toNumber(x));
}
@@ -170,7 +170,7 @@
* @return asin of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object asin(final Object self, final Object x) {
+ public static double asin(final Object self, final Object x) {
return Math.asin(JSType.toNumber(x));
}
@@ -196,7 +196,7 @@
* @return atan of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object atan(final Object self, final Object x) {
+ public static double atan(final Object self, final Object x) {
return Math.atan(JSType.toNumber(x));
}
@@ -223,7 +223,7 @@
* @return atan2 of x and y
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object atan2(final Object self, final Object y, final Object x) {
+ public static double atan2(final Object self, final Object y, final Object x) {
return Math.atan2(JSType.toNumber(y), JSType.toNumber(x));
}
@@ -250,7 +250,7 @@
* @return ceil of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object ceil(final Object self, final Object x) {
+ public static double ceil(final Object self, final Object x) {
return Math.ceil(JSType.toNumber(x));
}
@@ -302,7 +302,7 @@
* @return cos of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object cos(final Object self, final Object x) {
+ public static double cos(final Object self, final Object x) {
return Math.cos(JSType.toNumber(x));
}
@@ -328,7 +328,7 @@
* @return exp of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object exp(final Object self, final Object x) {
+ public static double exp(final Object self, final Object x) {
return Math.exp(JSType.toNumber(x));
}
@@ -341,7 +341,7 @@
* @return floor of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object floor(final Object self, final Object x) {
+ public static double floor(final Object self, final Object x) {
return Math.floor(JSType.toNumber(x));
}
@@ -393,7 +393,7 @@
* @return log of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object log(final Object self, final Object x) {
+ public static double log(final Object self, final Object x) {
return Math.log(JSType.toNumber(x));
}
@@ -419,7 +419,7 @@
* @return the largest of the arguments, {@link Double#NEGATIVE_INFINITY} if no args given, or identity if one arg is given
*/
@Function(arity = 2, attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object max(final Object self, final Object... args) {
+ public static double max(final Object self, final Object... args) {
switch (args.length) {
case 0:
return Double.NEGATIVE_INFINITY;
@@ -497,7 +497,7 @@
* @return the smallest of the arguments, {@link Double#NEGATIVE_INFINITY} if no args given, or identity if one arg is given
*/
@Function(arity = 2, attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object min(final Object self, final Object... args) {
+ public static double min(final Object self, final Object... args) {
switch (args.length) {
case 0:
return Double.POSITIVE_INFINITY;
@@ -576,7 +576,7 @@
* @return x raised to the power of y
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object pow(final Object self, final Object x, final Object y) {
+ public static double pow(final Object self, final Object x, final Object y) {
return Math.pow(JSType.toNumber(x), JSType.toNumber(y));
}
@@ -602,7 +602,7 @@
* @return random number in the range [0..1)
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object random(final Object self) {
+ public static double random(final Object self) {
return Math.random();
}
@@ -615,7 +615,7 @@
* @return x rounded
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object round(final Object self, final Object x) {
+ public static double round(final Object self, final Object x) {
final double d = JSType.toNumber(x);
if (Math.getExponent(d) >= 52) {
return d;
@@ -632,7 +632,7 @@
* @return sin of x
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object sin(final Object self, final Object x) {
+ public static double sin(final Object self, final Object x) {
return Math.sin(JSType.toNumber(x));
}
@@ -658,7 +658,7 @@
* @return sqrt of x
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object sqrt(final Object self, final Object x) {
+ public static double sqrt(final Object self, final Object x) {
return Math.sqrt(JSType.toNumber(x));
}
@@ -684,7 +684,7 @@
* @return tan of x
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where=Where.CONSTRUCTOR)
- public static Object tan(final Object self, final Object x) {
+ public static double tan(final Object self, final Object x) {
return Math.tan(JSType.toNumber(x));
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java b/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java
index d9d568b..a95587e 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java
@@ -34,6 +34,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.text.NumberFormat;
import java.util.Locale;
import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -57,7 +58,10 @@
@ScriptClass("Number")
public final class NativeNumber extends ScriptObject {
- static final MethodHandle WRAPFILTER = findWrapFilter();
+ // Method handle to create an object wrapper for a primitive number
+ private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class));
+ // Method handle to retrieve the Number prototype object
+ private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
/** ECMA 15.7.3.2 largest positive finite value */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT, where = Where.CONSTRUCTOR)
@@ -86,10 +90,6 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeNumber(final double value, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.value = value;
@@ -98,7 +98,7 @@
}
NativeNumber(final double value, final Global global) {
- this(value, global.getNumberPrototype(), global.getNumberMap());
+ this(value, global.getNumberPrototype(), $nasgenmap$);
}
private NativeNumber(final double value) {
@@ -185,7 +185,7 @@
* @return number in decimal fixed point notation
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toFixed(final Object self, final Object fractionDigits) {
+ public static String toFixed(final Object self, final Object fractionDigits) {
final int f = JSType.toInteger(fractionDigits);
if (f < 0 || f > 20) {
throw rangeError("invalid.fraction.digits", "toFixed");
@@ -217,7 +217,7 @@
* @return number in decimal exponential notation
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toExponential(final Object self, final Object fractionDigits) {
+ public static String toExponential(final Object self, final Object fractionDigits) {
final double x = getNumberValue(self);
final boolean trimZeros = fractionDigits == UNDEFINED;
final int f = trimZeros ? 16 : JSType.toInteger(fractionDigits);
@@ -245,7 +245,7 @@
* @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toPrecision(final Object self, final Object precision) {
+ public static String toPrecision(final Object self, final Object precision) {
final double x = getNumberValue(self);
if (precision == UNDEFINED) {
return JSType.toString(x);
@@ -278,7 +278,7 @@
* @return string representation of this Number in the given radix
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self, final Object radix) {
+ public static String toString(final Object self, final Object radix) {
if (radix != UNDEFINED) {
final int intRadix = JSType.toInteger(radix);
if (intRadix != 10) {
@@ -299,7 +299,7 @@
* @return localized string for this Number
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleString(final Object self) {
+ public static String toLocaleString(final Object self) {
return JSType.toString(getNumberValue(self));
}
@@ -308,10 +308,10 @@
* ECMA 15.7.4.4 Number.prototype.valueOf ( )
*
* @param self self reference
- * @return boxed number value for this Number
+ * @return number value for this Number
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object valueOf(final Object self) {
+ public static double valueOf(final Object self) {
return getNumberValue(self);
}
@@ -322,7 +322,7 @@
* @return Link to be invoked at call site.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
- return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER);
+ return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER);
}
@SuppressWarnings("unused")
@@ -330,6 +330,11 @@
return new NativeNumber(((Number)receiver).doubleValue());
}
+ @SuppressWarnings("unused")
+ private static Object protoFilter(final Object object) {
+ return Global.instance().getNumberPrototype();
+ }
+
private static double getNumberValue(final Object self) {
if (self instanceof Number) {
return ((Number)self).doubleValue();
@@ -378,7 +383,7 @@
return str;
}
- private static MethodHandle findWrapFilter() {
- return MH.findStatic(MethodHandles.lookup(), NativeNumber.class, "wrapFilter", MH.type(NativeNumber.class, Object.class));
+ private static MethodHandle findOwnMH(final String name, final MethodType type) {
+ return MH.findStatic(MethodHandles.lookup(), NativeNumber.class, name, type);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java
index d102c0f..9cde4fa 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java
@@ -31,6 +31,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -58,6 +59,7 @@
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
import jdk.nashorn.internal.runtime.linker.NashornBeansLinker;
@@ -101,6 +103,27 @@
}
/**
+ * Nashorn extension: setIndexedPropertiesToExternalArrayData
+ *
+ * @param self self reference
+ * @param obj object whose index properties are backed by buffer
+ * @param buf external buffer - should be a nio ByteBuffer
+ * @return the 'obj' object
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static ScriptObject setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) {
+ Global.checkObject(obj);
+ final ScriptObject sobj = (ScriptObject)obj;
+ if (buf instanceof ByteBuffer) {
+ sobj.setArray(ArrayData.allocate((ByteBuffer)buf));
+ } else {
+ throw typeError("not.a.bytebuffer", "setIndexedPropertiesToExternalArrayData's buf argument");
+ }
+ return sobj;
+ }
+
+
+ /**
* ECMA 15.2.3.2 Object.getPrototypeOf ( O )
*
* @param self self reference
@@ -180,7 +203,7 @@
* @return array of property names
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object getOwnPropertyNames(final Object self, final Object obj) {
+ public static ScriptObject getOwnPropertyNames(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
} else if (obj instanceof ScriptObjectMirror) {
@@ -199,7 +222,7 @@
* @return object created
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object create(final Object self, final Object proto, final Object props) {
+ public static ScriptObject create(final Object self, final Object proto, final Object props) {
if (proto != null) {
Global.checkObject(proto);
}
@@ -225,10 +248,11 @@
* @return object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
+ public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
Global.checkObject(obj);
- ((ScriptObject)obj).defineOwnProperty(JSType.toString(prop), attr, true);
- return obj;
+ final ScriptObject sobj = (ScriptObject)obj;
+ sobj.defineOwnProperty(JSType.toString(prop), attr, true);
+ return sobj;
}
/**
@@ -240,7 +264,7 @@
* @return object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object defineProperties(final Object self, final Object obj, final Object props) {
+ public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
Global.checkObject(obj);
final ScriptObject sobj = (ScriptObject)obj;
@@ -319,7 +343,7 @@
* @return true if sealed, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isSealed(final Object self, final Object obj) {
+ public static boolean isSealed(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isSealed();
} else if (obj instanceof ScriptObjectMirror) {
@@ -337,7 +361,7 @@
* @return true if object is frozen, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isFrozen(final Object self, final Object obj) {
+ public static boolean isFrozen(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isFrozen();
} else if (obj instanceof ScriptObjectMirror) {
@@ -355,7 +379,7 @@
* @return true if object is extensible, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isExtensible(final Object self, final Object obj) {
+ public static boolean isExtensible(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isExtensible();
} else if (obj instanceof ScriptObjectMirror) {
@@ -373,7 +397,7 @@
* @return array of keys in object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object keys(final Object self, final Object obj) {
+ public static ScriptObject keys(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
final ScriptObject sobj = (ScriptObject)obj;
return new NativeArray(sobj.getOwnKeys(false));
@@ -430,7 +454,7 @@
* @return ToString of object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return ScriptRuntime.builtinObjectToString(self);
}
@@ -483,7 +507,7 @@
* @return true if property exists in object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object hasOwnProperty(final Object self, final Object v) {
+ public static boolean hasOwnProperty(final Object self, final Object v) {
// Convert ScriptObjects to primitive with String.class hint
// but no need to convert other primitives to string.
final Object key = JSType.toPrimitive(v, String.class);
@@ -500,7 +524,7 @@
* @return true if object is prototype of v
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object isPrototypeOf(final Object self, final Object v) {
+ public static boolean isPrototypeOf(final Object self, final Object v) {
if (!(v instanceof ScriptObject)) {
return false;
}
@@ -526,7 +550,7 @@
* @return true if property is enumerable
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object propertyIsEnumerable(final Object self, final Object v) {
+ public static boolean propertyIsEnumerable(final Object self, final Object v) {
final String str = JSType.toString(v);
final Object obj = Global.toObject(self);
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java
index d51a0c0..ff3ac7b 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java
@@ -44,7 +44,7 @@
public final class NativeRangeError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,13 +55,14 @@
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
private NativeRangeError(final Object msg, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
if (msg != UNDEFINED) {
@@ -69,10 +70,11 @@
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
NativeRangeError(final Object msg, final Global global) {
- this(msg, global.getRangeErrorPrototype(), global.getRangeErrorMap());
+ this(msg, global.getRangeErrorPrototype(), $nasgenmap$);
}
private NativeRangeError(final Object msg) {
@@ -96,7 +98,7 @@
* @return new RangeError
*/
@Constructor(name = "RangeError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeRangeError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeRangeError(msg);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java
index a269b51..7419017 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java
@@ -44,7 +44,7 @@
public final class NativeReferenceError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,13 +55,14 @@
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
private NativeReferenceError(final Object msg, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
if (msg != UNDEFINED) {
@@ -69,10 +70,11 @@
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
NativeReferenceError(final Object msg, final Global global) {
- this(msg, global.getReferenceErrorPrototype(), global.getReferenceErrorMap());
+ this(msg, global.getReferenceErrorPrototype(), $nasgenmap$);
}
private NativeReferenceError(final Object msg) {
@@ -96,7 +98,7 @@
* @return new ReferenceError
*/
@Constructor(name = "ReferenceError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeReferenceError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeReferenceError(msg);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java
index 318ca2a..89a9a82 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java
@@ -70,12 +70,8 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeRegExp(final Global global) {
- super(global.getRegExpPrototype(), global.getRegExpMap());
+ super(global.getRegExpPrototype(), $nasgenmap$);
this.globalObject = global;
}
@@ -126,7 +122,7 @@
* @return new NativeRegExp
*/
@Constructor(arity = 2)
- public static Object constructor(final boolean isNew, final Object self, final Object... args) {
+ public static NativeRegExp constructor(final boolean isNew, final Object self, final Object... args) {
if (args.length > 1) {
return newRegExp(args[0], args[1]);
} else if (args.length > 0) {
@@ -146,7 +142,7 @@
* @return new NativeRegExp
*/
@SpecializedConstructor
- public static Object constructor(final boolean isNew, final Object self) {
+ public static NativeRegExp constructor(final boolean isNew, final Object self) {
return new NativeRegExp("", "");
}
@@ -161,7 +157,7 @@
* @return new NativeRegExp
*/
@SpecializedConstructor
- public static Object constructor(final boolean isNew, final Object self, final Object pattern) {
+ public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern) {
return newRegExp(pattern, UNDEFINED);
}
@@ -177,7 +173,7 @@
* @return new NativeRegExp
*/
@SpecializedConstructor
- public static Object constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) {
+ public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) {
return newRegExp(pattern, flags);
}
@@ -287,7 +283,7 @@
* @return new NativeRegExp
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object compile(final Object self, final Object pattern, final Object flags) {
+ public static ScriptObject compile(final Object self, final Object pattern, final Object flags) {
final NativeRegExp regExp = checkRegExp(self);
final NativeRegExp compiled = newRegExp(pattern, flags);
// copy over regexp to 'self'
@@ -306,7 +302,7 @@
* @return array containing the matches or {@code null} if no match
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object exec(final Object self, final Object string) {
+ public static ScriptObject exec(final Object self, final Object string) {
return checkRegExp(self).exec(JSType.toString(string));
}
@@ -318,7 +314,7 @@
* @return true if matches found, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object test(final Object self, final Object string) {
+ public static boolean test(final Object self, final Object string) {
return checkRegExp(self).test(JSType.toString(string));
}
@@ -329,7 +325,7 @@
* @return string version of regexp
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return checkRegExp(self).toString();
}
@@ -622,7 +618,7 @@
* @param string String to match.
* @return NativeArray of matches, string or null.
*/
- public Object exec(final String string) {
+ public NativeRegExpExecResult exec(final String string) {
final RegExpResult match = execInner(string);
if (match == null) {
@@ -639,7 +635,7 @@
* @param string String to match.
* @return True if a match is found.
*/
- public Object test(final String string) {
+ public boolean test(final String string) {
return execInner(string) != null;
}
@@ -653,7 +649,7 @@
* @param replacement Replacement string.
* @return String with substitutions.
*/
- Object replace(final String string, final String replacement, final ScriptFunction function) {
+ String replace(final String string, final String replacement, final ScriptFunction function) {
final RegExpMatcher matcher = regexp.match(string);
if (matcher == null) {
@@ -808,7 +804,7 @@
* @param limit Split limit.
* @return Array of substrings.
*/
- Object split(final String string, final long limit) {
+ NativeArray split(final String string, final long limit) {
if (limit == 0L) {
return new NativeArray();
}
@@ -871,7 +867,7 @@
* @param string String to match.
* @return Index of match.
*/
- Object search(final String string) {
+ int search(final String string) {
final RegExpResult match = execInner(string);
if (match == null) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
index 3508e5f..f12cea1 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
@@ -53,12 +53,8 @@
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
NativeRegExpExecResult(final RegExpResult result, final Global global) {
- super(global.getArrayPrototype(), global.getRegExpExecResultMap());
+ super(global.getArrayPrototype(), $nasgenmap$);
setIsArray();
this.setArray(ArrayData.allocate(result.getGroups().clone()));
this.index = result.getIndex();
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java b/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
index b81cc2a..dd2c281 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
@@ -60,9 +60,9 @@
// In strict mode, the caller and callee properties should throw TypeError
// Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
- map = map.addProperty(map.newUserAccessors("caller", flags));
- map = map.addProperty(map.newUserAccessors("callee", flags));
- map$ = map.setIsShared();
+ map = map.addPropertyNoHistory(map.newUserAccessors("caller", flags));
+ map = map.addPropertyNoHistory(map.newUserAccessors("callee", flags));
+ map$ = map;
}
static PropertyMap getInitialMap() {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java
index 95af71a..51edf75 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java
@@ -32,6 +32,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
@@ -69,21 +70,20 @@
private final CharSequence value;
- static final MethodHandle WRAPFILTER = findWrapFilter();
+ // Method handle to create an object wrapper for a primitive string
+ private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class));
+ // Method handle to retrieve the String prototype object
+ private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeString(final CharSequence value) {
this(value, Global.instance());
}
NativeString(final CharSequence value, final Global global) {
- this(value, global.getStringPrototype(), global.getStringMap());
+ this(value, global.getStringPrototype(), $nasgenmap$);
}
private NativeString(final CharSequence value, final ScriptObject proto, final PropertyMap map) {
@@ -425,7 +425,7 @@
* @return string with arguments translated to charcodes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1, where = Where.CONSTRUCTOR)
- public static Object fromCharCode(final Object self, final Object... args) {
+ public static String fromCharCode(final Object self, final Object... args) {
final char[] buf = new char[args.length];
int index = 0;
for (final Object arg : args) {
@@ -441,7 +441,7 @@
* @return string with one charcode
*/
@SpecializedFunction
- public static Object fromCharCode(final Object self, final Object value) {
+ public static String fromCharCode(final Object self, final Object value) {
try {
return "" + (char)JSType.toUint16(((Number)value).doubleValue());
} catch (final ClassCastException e) {
@@ -456,7 +456,7 @@
* @return string with one charcode
*/
@SpecializedFunction
- public static Object fromCharCode(final Object self, final int value) {
+ public static String fromCharCode(final Object self, final int value) {
return "" + (char)(value & 0xffff);
}
@@ -467,7 +467,7 @@
* @return string with one charcode
*/
@SpecializedFunction
- public static Object fromCharCode(final Object self, final long value) {
+ public static String fromCharCode(final Object self, final long value) {
return "" + (char)((int)value & 0xffff);
}
@@ -478,7 +478,7 @@
* @return string with one charcode
*/
@SpecializedFunction
- public static Object fromCharCode(final Object self, final double value) {
+ public static String fromCharCode(final Object self, final double value) {
return "" + (char)JSType.toUint16(value);
}
@@ -488,7 +488,7 @@
* @return self as string
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return getString(self);
}
@@ -498,7 +498,7 @@
* @return self as string
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object valueOf(final Object self) {
+ public static String valueOf(final Object self) {
return getString(self);
}
@@ -509,7 +509,7 @@
* @return string representing the char at the given position
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object charAt(final Object self, final Object pos) {
+ public static String charAt(final Object self, final Object pos) {
return charAtImpl(checkObjectToString(self), JSType.toInteger(pos));
}
@@ -546,7 +546,7 @@
* @return number representing charcode at position
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object charCodeAt(final Object self, final Object pos) {
+ public static double charCodeAt(final Object self, final Object pos) {
return charCodeAtImpl(checkObjectToString(self), JSType.toInteger(pos));
}
@@ -601,7 +601,7 @@
* @return position of first match or -1
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object indexOf(final Object self, final Object search, final Object pos) {
+ public static int indexOf(final Object self, final Object search, final Object pos) {
final String str = checkObjectToString(self);
return str.indexOf(JSType.toString(search), JSType.toInteger(pos));
}
@@ -649,7 +649,7 @@
* @return last position of match or -1
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object lastIndexOf(final Object self, final Object search, final Object pos) {
+ public static int lastIndexOf(final Object self, final Object search, final Object pos) {
final String str = checkObjectToString(self);
final String searchStr = JSType.toString(search);
@@ -680,7 +680,7 @@
* @return result of locale sensitive comparison operation between {@code self} and {@code that}
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object localeCompare(final Object self, final Object that) {
+ public static double localeCompare(final Object self, final Object that) {
final String str = checkObjectToString(self);
final Collator collator = Collator.getInstance(Global.getEnv()._locale);
@@ -698,7 +698,7 @@
* @return array of regexp matches
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object match(final Object self, final Object regexp) {
+ public static ScriptObject match(final Object self, final Object regexp) {
final String str = checkObjectToString(self);
@@ -745,7 +745,7 @@
* @return string after replacement
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object replace(final Object self, final Object string, final Object replacement) {
+ public static String replace(final Object self, final Object string, final Object replacement) {
final String str = checkObjectToString(self);
@@ -771,7 +771,7 @@
* @return offset where match occurred
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object search(final Object self, final Object string) {
+ public static int search(final Object self, final Object string) {
final String str = checkObjectToString(self);
final NativeRegExp nativeRegExp = Global.toRegExp(string == UNDEFINED ? "" : string);
@@ -788,7 +788,7 @@
* @return sliced out substring
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object slice(final Object self, final Object start, final Object end) {
+ public static String slice(final Object self, final Object start, final Object end) {
final String str = checkObjectToString(self);
if (end == UNDEFINED) {
@@ -805,7 +805,7 @@
* @return sliced out substring
*/
@SpecializedFunction
- public static Object slice(final Object self, final int start) {
+ public static String slice(final Object self, final int start) {
final String str = checkObjectToString(self);
final int from = (start < 0) ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
@@ -820,7 +820,7 @@
* @return sliced out substring
*/
@SpecializedFunction
- public static Object slice(final Object self, final double start) {
+ public static String slice(final Object self, final double start) {
return slice(self, (int)start);
}
@@ -833,7 +833,7 @@
* @return sliced out substring
*/
@SpecializedFunction
- public static Object slice(final Object self, final int start, final int end) {
+ public static String slice(final Object self, final int start, final int end) {
final String str = checkObjectToString(self);
final int len = str.length();
@@ -853,7 +853,7 @@
* @return sliced out substring
*/
@SpecializedFunction
- public static Object slice(final Object self, final double start, final double end) {
+ public static String slice(final Object self, final double start, final double end) {
return slice(self, (int)start, (int)end);
}
@@ -866,7 +866,7 @@
* @return array object in which splits have been placed
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object split(final Object self, final Object separator, final Object limit) {
+ public static ScriptObject split(final Object self, final Object separator, final Object limit) {
final String str = checkObjectToString(self);
final long lim = (limit == UNDEFINED) ? JSType.MAX_UINT : JSType.toUint32(limit);
@@ -882,7 +882,7 @@
return splitString(str, JSType.toString(separator), lim);
}
- private static Object splitString(String str, String separator, long limit) {
+ private static ScriptObject splitString(String str, String separator, long limit) {
if (separator.isEmpty()) {
final int length = (int) Math.min(str.length(), limit);
final Object[] array = new Object[length];
@@ -923,7 +923,7 @@
* @return substring given start and length of section
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object substr(final Object self, final Object start, final Object length) {
+ public static String substr(final Object self, final Object start, final Object length) {
final String str = JSType.toString(self);
final int strLength = str.length();
@@ -946,7 +946,7 @@
* @return substring given start and end indexes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object substring(final Object self, final Object start, final Object end) {
+ public static String substring(final Object self, final Object start, final Object end) {
final String str = checkObjectToString(self);
if (end == UNDEFINED) {
@@ -1026,7 +1026,7 @@
* @return string to lower case
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLowerCase(final Object self) {
+ public static String toLowerCase(final Object self) {
return checkObjectToString(self).toLowerCase(Locale.ROOT);
}
@@ -1036,7 +1036,7 @@
* @return string to locale sensitive lower case
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleLowerCase(final Object self) {
+ public static String toLocaleLowerCase(final Object self) {
return checkObjectToString(self).toLowerCase(Global.getEnv()._locale);
}
@@ -1046,7 +1046,7 @@
* @return string to upper case
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toUpperCase(final Object self) {
+ public static String toUpperCase(final Object self) {
return checkObjectToString(self).toUpperCase(Locale.ROOT);
}
@@ -1056,7 +1056,7 @@
* @return string to locale sensitive upper case
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleUpperCase(final Object self) {
+ public static String toLocaleUpperCase(final Object self) {
return checkObjectToString(self).toUpperCase(Global.getEnv()._locale);
}
@@ -1066,7 +1066,7 @@
* @return string trimmed from whitespace
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object trim(final Object self) {
+ public static String trim(final Object self) {
final String str = checkObjectToString(self);
int start = 0;
@@ -1088,7 +1088,7 @@
* @return string trimmed left from whitespace
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object trimLeft(final Object self) {
+ public static String trimLeft(final Object self) {
final String str = checkObjectToString(self);
int start = 0;
@@ -1107,7 +1107,7 @@
* @return string trimmed right from whitespace
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object trimRight(final Object self) {
+ public static String trimRight(final Object self) {
final String str = checkObjectToString(self);
int start = 0;
@@ -1120,7 +1120,7 @@
return str.substring(start, end + 1);
}
- private static Object newObj(final Object self, final CharSequence str) {
+ private static ScriptObject newObj(final Object self, final CharSequence str) {
return new NativeString(str);
}
@@ -1199,7 +1199,7 @@
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
final MethodHandle guard = NashornGuards.getInstanceOf2Guard(String.class, ConsString.class);
- return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER);
+ return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER);
}
@SuppressWarnings("unused")
@@ -1207,6 +1207,11 @@
return new NativeString((CharSequence)receiver);
}
+ @SuppressWarnings("unused")
+ private static Object protoFilter(final Object object) {
+ return Global.instance().getStringPrototype();
+ }
+
private static CharSequence getCharSequence(final Object self) {
if (self instanceof String || self instanceof ConsString) {
return (CharSequence)self;
@@ -1254,7 +1259,7 @@
return key >= 0 && key < value.length();
}
- private static MethodHandle findWrapFilter() {
- return MH.findStatic(MethodHandles.lookup(), NativeString.class, "wrapFilter", MH.type(NativeString.class, Object.class));
+ private static MethodHandle findOwnMH(final String name, final MethodType type) {
+ return MH.findStatic(MethodHandles.lookup(), NativeString.class, name, type);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
index 45920ba..db7debb 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
@@ -44,7 +44,7 @@
public final class NativeSyntaxError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,20 +55,22 @@
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
NativeSyntaxError(final Object msg, final Global global) {
- super(global.getSyntaxErrorPrototype(), global.getSyntaxErrorMap());
+ super(global.getSyntaxErrorPrototype(), $nasgenmap$);
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
private NativeSyntaxError(final Object msg) {
@@ -92,7 +94,7 @@
* @return new SyntaxError
*/
@Constructor(name = "SyntaxError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeSyntaxError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeSyntaxError(msg);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java
index 2b2308b..6e5a493 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java
@@ -44,7 +44,7 @@
public final class NativeTypeError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,20 +55,22 @@
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
NativeTypeError(final Object msg, final Global global) {
- super(global.getTypeErrorPrototype(), global.getTypeErrorMap());
+ super(global.getTypeErrorPrototype(), $nasgenmap$);
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
private NativeTypeError(final Object msg) {
@@ -92,7 +94,7 @@
* @return new TypeError
*/
@Constructor(name = "TypeError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeTypeError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeTypeError(msg);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java
index 2caf136..cf5fdaa 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java
@@ -43,7 +43,7 @@
public final class NativeURIError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -54,20 +54,22 @@
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
NativeURIError(final Object msg, final Global global) {
- super(global.getURIErrorPrototype(), global.getURIErrorMap());
+ super(global.getURIErrorPrototype(), $nasgenmap$);
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
private NativeURIError(final Object msg) {
@@ -91,7 +93,7 @@
* @return new URIError
*/
@Constructor(name = "URIError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeURIError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeURIError(msg);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
index ee91aef..8aa3d62 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
@@ -99,8 +99,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeUint16Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeUint16Array)constructorImpl(args, FACTORY);
}
NativeUint16Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -150,8 +150,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeUint16Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeUint16Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
index 58909db..7381224 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
@@ -118,8 +118,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeUint32Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeUint32Array)constructorImpl(args, FACTORY);
}
NativeUint32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -169,8 +169,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeUint32Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeUint32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
index 0db1bee..1f30456 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
@@ -92,8 +92,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeUint8Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeUint8Array)constructorImpl(args, FACTORY);
}
NativeUint8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -143,8 +143,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeUint8Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeUint8Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
index f0db743..d757ee3 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
@@ -109,8 +109,8 @@
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeUint8ClampedArray constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeUint8ClampedArray)constructorImpl(args, FACTORY);
}
NativeUint8ClampedArray(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -160,8 +160,8 @@
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeUint8ClampedArray subarray(final Object self, final Object begin, final Object end) {
+ return (NativeUint8ClampedArray)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java b/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java
index 4610afc..483f617 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java
@@ -54,16 +54,11 @@
static {
final ArrayList<Property> properties = new ArrayList<>(1);
properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR));
- map$ = PropertyMap.newMap(properties).setIsShared();
- }
-
- static PropertyMap getInitialMap() {
- return map$;
+ map$ = PropertyMap.newMap(properties);
}
private PrototypeObject(final Global global, final PropertyMap map) {
- super(map != map$? map.addAll(global.getPrototypeObjectMap()) : global.getPrototypeObjectMap());
- setProto(global.getObjectPrototype());
+ super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$);
}
PrototypeObject() {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
index f0bea3a..dcbc7da 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
@@ -37,7 +37,6 @@
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.runtime.AccessorProperty;
/**
@@ -56,27 +55,11 @@
// property map for non-strict, non-bound functions.
private static final PropertyMap map$;
- static PropertyMap getInitialMap() {
- return map$;
- }
-
- static PropertyMap getInitialAnonymousMap() {
- return AnonymousFunction.getInitialMap();
- }
-
- static PropertyMap getInitialStrictMap() {
- return strictmodemap$;
- }
-
- static PropertyMap getInitialBoundMap() {
- return boundfunctionmap$;
- }
-
// Marker object for lazily initialized prototype object
private static final Object LAZY_PROTOTYPE = new Object();
private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) {
- super(name, invokeHandle, global.getFunctionMap(), null, specs, false, true, true);
+ super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
init(global);
}
@@ -93,7 +76,7 @@
}
private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) {
- super(name, invokeHandle, map.addAll(global.getFunctionMap()), null, specs, false, true, true);
+ super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
init(global);
}
@@ -110,8 +93,8 @@
this(name, invokeHandle, map, specs, Global.instance());
}
- private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor, final Global global) {
- super(name, methodHandle, getMap(global, isStrict), scope, specs, isStrict, isBuiltin, isConstructor);
+ private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags, final Global global) {
+ super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags);
init(global);
}
@@ -122,16 +105,14 @@
* @param methodHandle handle for invocation
* @param scope scope object
* @param specs specialized versions of this method, if available, null otherwise
- * @param isStrict are we in strict mode
- * @param isBuiltin is this a built-in function
- * @param isConstructor can the function be used as a constructor (most can; some built-ins are restricted).
+ * @param flags {@link ScriptFunctionData} flags
*/
- ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
- this(name, methodHandle, scope, specs, isStrict, isBuiltin, isConstructor, Global.instance());
+ ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags) {
+ this(name, methodHandle, scope, specs, flags, Global.instance());
}
private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) {
- super(data, getMap(global, data.isStrict()), scope);
+ super(data, getMap(data.isStrict()), scope);
init(global);
}
@@ -151,7 +132,7 @@
* @param global the global object
*/
ScriptFunctionImpl(final ScriptFunctionData data, final Global global) {
- super(data, global.getBoundFunctionMap(), null);
+ super(data, boundfunctionmap$, null);
init(global);
}
@@ -163,25 +144,24 @@
map$ = PropertyMap.newMap(properties);
strictmodemap$ = createStrictModeMap(map$);
boundfunctionmap$ = createBoundFunctionMap(strictmodemap$);
- // There are order dependencies between normal map, struct map and bound map
- // We can make these 'shared' only after initialization of all three.
- map$.setIsShared();
- strictmodemap$.setIsShared();
- boundfunctionmap$.setIsShared();
}
private static PropertyMap createStrictModeMap(final PropertyMap map) {
final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
PropertyMap newMap = map;
// Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
- newMap = newMap.addProperty(map.newUserAccessors("arguments", flags));
- newMap = newMap.addProperty(map.newUserAccessors("caller", flags));
+ newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags));
+ newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags));
return newMap;
}
+ private static boolean isStrict(final int flags) {
+ return (flags & ScriptFunctionData.IS_STRICT) != 0;
+ }
+
// Choose the map based on strict mode!
- private static PropertyMap getMap(final Global global, final boolean strict) {
- return strict ? global.getStrictFunctionMap() : global.getFunctionMap();
+ private static PropertyMap getMap(final boolean strict) {
+ return strict ? strictmodemap$ : map$;
}
private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) {
@@ -193,14 +173,10 @@
// Instance of this class is used as global anonymous function which
// serves as Function.prototype object.
private static class AnonymousFunction extends ScriptFunctionImpl {
- private static final PropertyMap anonmap$ = PropertyMap.newMap().setIsShared();
-
- static PropertyMap getInitialMap() {
- return anonmap$;
- }
+ private static final PropertyMap anonmap$ = PropertyMap.newMap();
AnonymousFunction(final Global global) {
- super("", GlobalFunctions.ANONYMOUS, global.getAnonymousFunctionMap(), null);
+ super("", GlobalFunctions.ANONYMOUS, anonmap$, null);
}
}
@@ -217,7 +193,7 @@
* @return new ScriptFunction
*/
static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
- final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, false, true, false);
+ final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN);
func.setPrototype(UNDEFINED);
// Non-constructor built-in functions do not have "prototype" property
func.deleteOwnProperty(func.getMap().findProperty("prototype"));
@@ -281,13 +257,17 @@
}
@Override
- public final void setPrototype(final Object prototype) {
- this.prototype = prototype;
+ public final void setPrototype(final Object newProto) {
+ if (newProto instanceof ScriptObject && newProto != this.prototype && allocatorMap != null) {
+ // Replace our current allocator map with one that is associated with the new prototype.
+ allocatorMap = allocatorMap.changeProto((ScriptObject)newProto);
+ }
+ this.prototype = newProto;
}
// Internals below..
private void init(final Global global) {
- this.setProto(global.getFunctionPrototype());
+ this.setInitialProto(global.getFunctionPrototype());
this.prototype = LAZY_PROTOTYPE;
// We have to fill user accessor functions late as these are stored
diff --git a/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java b/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java
index 587ae86..d4a42ba 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.parser;
import static jdk.nashorn.internal.parser.TokenType.COMMENT;
+import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
import static jdk.nashorn.internal.parser.TokenType.EOF;
import static jdk.nashorn.internal.parser.TokenType.EOL;
import static jdk.nashorn.internal.parser.TokenType.IDENT;
@@ -84,6 +85,9 @@
/** Is this parser running under strict mode? */
protected boolean isStrictMode;
+ /** //@ sourceURL or //# sourceURL */
+ protected String sourceURL;
+
/**
* Construct a parser.
*
@@ -156,17 +160,38 @@
protected final TokenType nextOrEOL() {
do {
nextToken();
- } while (type == COMMENT);
+ if (type == DIRECTIVE_COMMENT) {
+ checkDirectiveComment();
+ }
+ } while (type == COMMENT || type == DIRECTIVE_COMMENT);
return type;
}
+ // sourceURL= after directive comment
+ private static final String SOURCE_URL_PREFIX = "sourceURL=";
+
+ // currently only @sourceURL=foo supported
+ private void checkDirectiveComment() {
+ // if already set, ignore this one
+ if (sourceURL != null) {
+ return;
+ }
+
+ final String comment = (String) lexer.getValueOf(token, isStrictMode);
+ final int len = comment.length();
+ // 4 characters for directive comment marker //@\s or //#\s
+ if (len > 4 && comment.substring(4).startsWith(SOURCE_URL_PREFIX)) {
+ sourceURL = comment.substring(4 + SOURCE_URL_PREFIX.length());
+ }
+ }
+
/**
* Seek next token.
*
* @return tokenType of next token.
*/
- private final TokenType nextToken() {
+ private TokenType nextToken() {
// Capture last token tokenType.
last = type;
if (type != EOF) {
diff --git a/nashorn/src/jdk/nashorn/internal/parser/Lexer.java b/nashorn/src/jdk/nashorn/internal/parser/Lexer.java
index a01705d..653f04c 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/Lexer.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/Lexer.java
@@ -27,6 +27,7 @@
import static jdk.nashorn.internal.parser.TokenType.ADD;
import static jdk.nashorn.internal.parser.TokenType.COMMENT;
+import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
import static jdk.nashorn.internal.parser.TokenType.DECIMAL;
import static jdk.nashorn.internal.parser.TokenType.EOF;
import static jdk.nashorn.internal.parser.TokenType.EOL;
@@ -434,12 +435,18 @@
if (ch1 == '/') {
// Skip over //.
skip(2);
+
+ boolean directiveComment = false;
+ if ((ch0 == '#' || ch0 == '@') && (ch1 == ' ')) {
+ directiveComment = true;
+ }
+
// Scan for EOL.
while (!atEOF() && !isEOL(ch0)) {
skip(1);
}
// Did detect a comment.
- add(COMMENT, start);
+ add(directiveComment? DIRECTIVE_COMMENT : COMMENT, start);
return true;
} else if (ch1 == '*') {
// Skip over /*.
@@ -1623,6 +1630,8 @@
return valueOfPattern(start, len); // RegexToken::LexerToken
case XML:
return valueOfXML(start, len); // XMLToken::LexerToken
+ case DIRECTIVE_COMMENT:
+ return source.getString(start, len);
default:
break;
}
diff --git a/nashorn/src/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk/nashorn/internal/parser/Parser.java
index 8e04fdc..08ff725 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java
@@ -26,7 +26,7 @@
package jdk.nashorn.internal.parser;
import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
-import static jdk.nashorn.internal.codegen.CompilerConstants.FUNCTION_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
import static jdk.nashorn.internal.parser.TokenType.CASE;
@@ -389,7 +389,9 @@
sb.append(parentFunction.getName()).append('$');
}
- sb.append(ident != null ? ident.getName() : FUNCTION_PREFIX.symbolName());
+ assert ident.getName() != null;
+ sb.append(ident.getName());
+
final String name = namespace.uniqueName(sb.toString());
assert parentFunction != null || name.equals(RUN_SCRIPT.symbolName()) : "name = " + name;// must not rename runScript().
@@ -419,7 +421,8 @@
name,
parameters,
kind,
- flags);
+ flags,
+ sourceURL);
lc.push(functionNode);
// Create new block, and just put it on the context stack, restoreFunctionNode() will associate it with the
@@ -638,6 +641,10 @@
script = restoreFunctionNode(script, token); //commit code
script = script.setBody(lc, script.getBody().setNeedsScope(lc));
+ // user may have directive comment to set sourceURL
+ if (sourceURL != null) {
+ script = script.setSourceURL(lc, sourceURL);
+ }
return script;
}
@@ -1693,9 +1700,11 @@
// ECMA 12.4.1 strict mode restrictions
verifyStrictIdent(exception, "catch argument");
- // Check for conditional catch.
+ // Nashorn extension: catch clause can have optional
+ // condition. So, a single try can have more than one
+ // catch clause each with it's own condition.
final Expression ifExpression;
- if (type == IF) {
+ if (!env._no_syntax_extensions && type == IF) {
next();
// Get the exception condition.
ifExpression = expression();
@@ -1792,6 +1801,7 @@
case THIS:
final String name = type.getName();
next();
+ lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_THIS);
return new IdentNode(primaryToken, finish, name);
case IDENT:
final IdentNode ident = getIdent();
@@ -2132,11 +2142,20 @@
final String setterName = setIdent.getPropertyName();
final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
expect(LPAREN);
- final IdentNode argIdent = getIdent();
- verifyStrictIdent(argIdent, "setter argument");
+ // be sloppy and allow missing setter parameter even though
+ // spec does not permit it!
+ final IdentNode argIdent;
+ if (type == IDENT || isNonStrictModeIdent()) {
+ argIdent = getIdent();
+ verifyStrictIdent(argIdent, "setter argument");
+ } else {
+ argIdent = null;
+ }
expect(RPAREN);
List<IdentNode> parameters = new ArrayList<>();
- parameters.add(argIdent);
+ if (argIdent != null) {
+ parameters.add(argIdent);
+ }
functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER);
return new PropertyNode(propertyToken, finish, setIdent, null, null, functionNode);
@@ -2448,7 +2467,7 @@
// name is null, generate anonymous name
boolean isAnonymous = false;
if (name == null) {
- final String tmpName = "_L" + functionLine;
+ final String tmpName = ANON_FUNCTION_PREFIX.symbolName() + functionLine;
name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
isAnonymous = true;
}
diff --git a/nashorn/src/jdk/nashorn/internal/parser/TokenType.java b/nashorn/src/jdk/nashorn/internal/parser/TokenType.java
index 6287a23..5c696cb 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/TokenType.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/TokenType.java
@@ -41,10 +41,14 @@
*/
@SuppressWarnings("javadoc")
public enum TokenType {
- ERROR (SPECIAL, null),
- EOF (SPECIAL, null),
- EOL (SPECIAL, null),
- COMMENT (SPECIAL, null),
+ ERROR (SPECIAL, null),
+ EOF (SPECIAL, null),
+ EOL (SPECIAL, null),
+ COMMENT (SPECIAL, null),
+ // comments of the form //@ foo=bar or //# foo=bar
+ // These comments are treated as special instructions
+ // to the lexer, parser or codegenerator.
+ DIRECTIVE_COMMENT (SPECIAL, null),
NOT (UNARY, "!", 14, false),
NE (BINARY, "!=", 9, true),
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java
index 702ca76..d22a956 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java
@@ -141,10 +141,12 @@
private Class<?> currentType;
/**
- * Delegate constructor. This is used when adding properties to the Global scope, which
- * is necessary for outermost levels in a script (the ScriptObject is represented by
- * a JO-prefixed ScriptObject class, but the properties need to be in the Global scope
- * and are thus rebound with that as receiver
+ * Delegate constructor for bound properties. This is used for properties created by
+ * {@link ScriptRuntime#mergeScope} and the Nashorn {@code Object.bindProperties} method.
+ * The former is used to add a script's defined globals to the current global scope while
+ * still storing them in a JO-prefixed ScriptObject class.
+ *
+ * <p>All properties created by this constructor have the {@link #IS_BOUND} flag set.</p>
*
* @param property accessor property to rebind
* @param delegate delegate object to rebind receiver to
@@ -157,6 +159,8 @@
this.objectGetter = bindTo(property.ensureObjectGetter(), delegate);
this.objectSetter = bindTo(property.ensureObjectSetter(), delegate);
+ // Properties created this way are bound to a delegate
+ this.flags |= IS_BOUND;
setCurrentType(property.getCurrentType());
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk/nashorn/internal/runtime/Context.java
index 86b5abd..eae6a3c 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java
@@ -36,6 +36,8 @@
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
import java.lang.reflect.Modifier;
import java.util.concurrent.atomic.AtomicLong;
import java.net.MalformedURLException;
@@ -47,6 +49,7 @@
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
+import java.util.LinkedHashMap;
import java.util.Map;
import jdk.internal.org.objectweb.asm.ClassReader;
@@ -91,6 +94,11 @@
*/
public static final String NASHORN_JAVA_REFLECTION = "nashorn.JavaReflection";
+ /**
+ * Permission to enable nashorn debug mode.
+ */
+ public static final String NASHORN_DEBUG_MODE = "nashorn.debugMode";
+
// nashorn load psuedo URL prefixes
private static final String LOAD_CLASSPATH = "classpath:";
private static final String LOAD_FX = "fx:";
@@ -149,16 +157,19 @@
/** Is Context global debug mode enabled ? */
public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
- private static final ThreadLocal<ScriptObject> currentGlobal = new ThreadLocal<>();
+ private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();
+
+ // class cache
+ private ClassCache classCache;
/**
* Get the current global scope
* @return the current global scope
*/
- public static ScriptObject getGlobal() {
+ public static Global getGlobal() {
// This class in a package.access protected package.
// Trusted code only can call this method.
- return getGlobalTrusted();
+ return currentGlobal.get();
}
/**
@@ -167,10 +178,19 @@
*/
public static void setGlobal(final ScriptObject global) {
if (global != null && !(global instanceof Global)) {
- throw new IllegalArgumentException("global is not an instance of Global!");
+ throw new IllegalArgumentException("not a global!");
}
+ setGlobal((Global)global);
+ }
- setGlobalTrusted(global);
+ /**
+ * Set the current global scope
+ * @param global the global scope
+ */
+ public static void setGlobal(final Global global) {
+ // This class in a package.access protected package.
+ // Trusted code only can call this method.
+ currentGlobal.set(global);
}
/**
@@ -191,7 +211,7 @@
* @return error writer of the current context
*/
public static PrintWriter getCurrentErr() {
- final ScriptObject global = getGlobalTrusted();
+ final ScriptObject global = getGlobal();
return (global != null)? global.getContext().getErr() : new PrintWriter(System.err);
}
@@ -344,6 +364,11 @@
this.classPathLoader = null;
}
+ final int cacheSize = env._class_cache_size;
+ if (cacheSize > 0) {
+ classCache = new ClassCache(cacheSize);
+ }
+
// print version info if asked.
if (env._version) {
getErr().println("nashorn " + Version.version());
@@ -391,7 +416,7 @@
* @return the property map of the current global scope
*/
public static PropertyMap getGlobalMap() {
- return Context.getGlobalTrusted().getMap();
+ return Context.getGlobal().getMap();
}
/**
@@ -421,7 +446,7 @@
final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
final Source source = new Source(file, string);
final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
ScriptObject scope = initialScope;
@@ -453,7 +478,7 @@
// in the caller's environment. A new environment is created!
if (strictFlag) {
// Create a new scope object
- final ScriptObject strictEvalScope = ((GlobalObject)global).newObject();
+ final ScriptObject strictEvalScope = global.newObject();
// bless it as a "scope"
strictEvalScope.setIsScope();
@@ -578,10 +603,10 @@
* @throws IOException if source cannot be found or loaded
*/
public Object loadWithNewGlobal(final Object from, final Object...args) throws IOException {
- final ScriptObject oldGlobal = getGlobalTrusted();
- final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
+ final Global oldGlobal = getGlobal();
+ final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
@Override
- public ScriptObject run() {
+ public Global run() {
try {
return newGlobal();
} catch (final RuntimeException e) {
@@ -594,17 +619,17 @@
}, CREATE_GLOBAL_ACC_CTXT);
// initialize newly created Global instance
initGlobal(newGlobal);
- setGlobalTrusted(newGlobal);
+ setGlobal(newGlobal);
final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY : ScriptObjectMirror.wrapArray(args, oldGlobal);
- newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped), env._strict);
+ newGlobal.put("arguments", newGlobal.wrapAsObject(wrapped), env._strict);
try {
// wrap objects from newGlobal's world as mirrors - but if result
// is from oldGlobal's world, unwrap it!
return ScriptObjectMirror.unwrap(ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal), oldGlobal);
} finally {
- setGlobalTrusted(oldGlobal);
+ setGlobal(oldGlobal);
}
}
@@ -633,7 +658,7 @@
* Checks that the given Class can be accessed from no permissions context.
*
* @param clazz Class object
- * @throw SecurityException if not accessible
+ * @throws SecurityException if not accessible
*/
public static void checkPackageAccess(final Class<?> clazz) {
final SecurityManager sm = System.getSecurityManager();
@@ -650,12 +675,12 @@
* Checks that the given package name can be accessed from no permissions context.
*
* @param pkgName package name
- * @throw SecurityException if not accessible
+ * @throws SecurityException if not accessible
*/
public static void checkPackageAccess(final String pkgName) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- checkPackageAccess(sm, pkgName.endsWith(".")? pkgName : pkgName + ".");
+ checkPackageAccess(sm, pkgName.endsWith(".") ? pkgName : pkgName + ".");
}
}
@@ -779,7 +804,7 @@
*
* @return the initialized global scope object.
*/
- public ScriptObject createGlobal() {
+ public Global createGlobal() {
return initGlobal(newGlobal());
}
@@ -787,7 +812,7 @@
* Create a new uninitialized global scope object
* @return the global script object
*/
- public ScriptObject newGlobal() {
+ public Global newGlobal() {
return new Global(this);
}
@@ -797,20 +822,16 @@
* @param global the global
* @return the initialized global scope object.
*/
- public ScriptObject initGlobal(final ScriptObject global) {
- if (! (global instanceof GlobalObject)) {
- throw new IllegalArgumentException("not a global object!");
- }
-
+ public Global initGlobal(final Global global) {
// Need only minimal global object, if we are just compiling.
if (!env._compile_only) {
- final ScriptObject oldGlobal = Context.getGlobalTrusted();
+ final Global oldGlobal = Context.getGlobal();
try {
- Context.setGlobalTrusted(global);
+ Context.setGlobal(global);
// initialize global scope with builtin global objects
- ((GlobalObject)global).initBuiltinObjects();
+ global.initBuiltinObjects();
} finally {
- Context.setGlobalTrusted(oldGlobal);
+ Context.setGlobal(oldGlobal);
}
}
@@ -818,30 +839,15 @@
}
/**
- * Trusted variants - package-private
+ * Trusted variant - package-private
*/
/**
- * Return the current global scope
- * @return current global scope
- */
- static ScriptObject getGlobalTrusted() {
- return currentGlobal.get();
- }
-
- /**
- * Set the current global scope
- */
- static void setGlobalTrusted(ScriptObject global) {
- currentGlobal.set(global);
- }
-
- /**
* Return the current global's context
* @return current global's context
*/
static Context getContextTrusted() {
- return Context.getGlobalTrusted().getContext();
+ return ((ScriptObject)Context.getGlobal()).getContext();
}
/**
@@ -910,7 +916,7 @@
}
// Package as a JavaScript function and pass function back to shell.
- return ((GlobalObject)Context.getGlobalTrusted()).newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
+ return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
}
private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
@@ -921,16 +927,10 @@
// start with no errors, no warnings.
errMan.reset();
- GlobalObject global = null;
- Class<?> script;
-
- if (env._class_cache_size > 0) {
- global = (GlobalObject)Context.getGlobalTrusted();
- script = global.findCachedClass(source);
- if (script != null) {
- Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
- return script;
- }
+ Class<?> script = findCachedClass(source);
+ if (script != null) {
+ Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
+ return script;
}
final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
@@ -952,17 +952,14 @@
final URL url = source.getURL();
final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
- final CodeSource cs = url == null ? null : new CodeSource(url, (CodeSigner[])null);
+ final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
final Compiler compiler = new Compiler(installer, strict);
final FunctionNode newFunctionNode = compiler.compile(functionNode);
script = compiler.install(newFunctionNode);
-
- if (global != null) {
- global.cacheClass(source, script);
- }
+ cacheClass(source, script);
return script;
}
@@ -984,4 +981,60 @@
private long getUniqueScriptId() {
return uniqueScriptId.getAndIncrement();
}
+
+ /**
+ * Cache for compiled script classes.
+ */
+ @SuppressWarnings("serial")
+ private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
+ private final int size;
+ private final ReferenceQueue<Class<?>> queue;
+
+ ClassCache(int size) {
+ super(size, 0.75f, true);
+ this.size = size;
+ this.queue = new ReferenceQueue<>();
+ }
+
+ void cache(final Source source, final Class<?> clazz) {
+ put(source, new ClassReference(clazz, queue, source));
+ }
+
+ @Override
+ protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
+ return size() > size;
+ }
+
+ @Override
+ public ClassReference get(Object key) {
+ for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
+ remove(ref.source);
+ }
+ return super.get(key);
+ }
+
+ }
+
+ private static class ClassReference extends SoftReference<Class<?>> {
+ private final Source source;
+
+ ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
+ super(clazz, queue);
+ this.source = source;
+ }
+ }
+
+ // Class cache management
+ private Class<?> findCachedClass(final Source source) {
+ ClassReference ref = classCache == null ? null : classCache.get(source);
+ return ref != null ? ref.get() : null;
+ }
+
+ private void cacheClass(final Source source, final Class<?> clazz) {
+ if (classCache != null) {
+ classCache.cache(source, clazz);
+ }
+ }
+
+
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java b/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
index c288a96..261bc02 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
@@ -75,7 +75,7 @@
* @return context global.
*/
static Object getGlobal() {
- return Context.getGlobalTrusted();
+ return Context.getGlobal();
}
/**
@@ -87,7 +87,7 @@
* @return Result of eval as string, or, an exception or null depending on returnException.
*/
static Object eval(final ScriptObject scope, final Object self, final String string, final boolean returnException) {
- final ScriptObject global = Context.getGlobalTrusted();
+ final ScriptObject global = Context.getGlobal();
final ScriptObject initialScope = scope != null ? scope : global;
final Object callThis = self != null ? self : global;
final Context context = global.getContext();
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java b/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java
index 0ff843a..affba49 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java
@@ -30,6 +30,8 @@
import java.util.ResourceBundle;
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.scripts.JS;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.objects.Global;
/**
* Helper class to throw various standard "ECMA error" exceptions such as Error, ReferenceError, TypeError etc.
@@ -65,7 +67,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException asEcmaException(final ParserException e) {
- return asEcmaException(Context.getGlobalTrusted(), e);
+ return asEcmaException(Context.getGlobal(), e);
}
/**
@@ -77,11 +79,11 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException asEcmaException(final ScriptObject global, final ParserException e) {
+ public static ECMAException asEcmaException(final Global global, final ParserException e) {
final JSErrorType errorType = e.getErrorType();
assert errorType != null : "error type for " + e + " was null";
- final GlobalObject globalObj = (GlobalObject)global;
+ final Global globalObj = global;
final String msg = e.getMessage();
// translate to ECMAScript Error object using error type
@@ -115,7 +117,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException syntaxError(final String msgId, final String... args) {
- return syntaxError(Context.getGlobalTrusted(), msgId, args);
+ return syntaxError(Context.getGlobal(), msgId, args);
}
/**
@@ -127,7 +129,7 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException syntaxError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException syntaxError(final Global global, final String msgId, final String... args) {
return syntaxError(global, null, msgId, args);
}
@@ -141,7 +143,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException syntaxError(final Throwable cause, final String msgId, final String... args) {
- return syntaxError(Context.getGlobalTrusted(), cause, msgId, args);
+ return syntaxError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -154,9 +156,9 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException syntaxError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException syntaxError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("syntax.error." + msgId, args);
- return error(((GlobalObject)global).newSyntaxError(msg), cause);
+ return error(global.newSyntaxError(msg), cause);
}
/**
@@ -168,7 +170,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException typeError(final String msgId, final String... args) {
- return typeError(Context.getGlobalTrusted(), msgId, args);
+ return typeError(Context.getGlobal(), msgId, args);
}
/**
@@ -180,7 +182,7 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException typeError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException typeError(final Global global, final String msgId, final String... args) {
return typeError(global, null, msgId, args);
}
@@ -194,7 +196,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException typeError(final Throwable cause, final String msgId, final String... args) {
- return typeError(Context.getGlobalTrusted(), cause, msgId, args);
+ return typeError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -207,9 +209,9 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException typeError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException typeError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("type.error." + msgId, args);
- return error(((GlobalObject)global).newTypeError(msg), cause);
+ return error(global.newTypeError(msg), cause);
}
/**
@@ -221,7 +223,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException rangeError(final String msgId, final String... args) {
- return rangeError(Context.getGlobalTrusted(), msgId, args);
+ return rangeError(Context.getGlobal(), msgId, args);
}
/**
@@ -233,7 +235,7 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException rangeError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException rangeError(final Global global, final String msgId, final String... args) {
return rangeError(global, null, msgId, args);
}
@@ -247,7 +249,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException rangeError(final Throwable cause, final String msgId, final String... args) {
- return rangeError(Context.getGlobalTrusted(), cause, msgId, args);
+ return rangeError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -260,9 +262,9 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException rangeError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException rangeError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("range.error." + msgId, args);
- return error(((GlobalObject)global).newRangeError(msg), cause);
+ return error(global.newRangeError(msg), cause);
}
/**
@@ -274,7 +276,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException referenceError(final String msgId, final String... args) {
- return referenceError(Context.getGlobalTrusted(), msgId, args);
+ return referenceError(Context.getGlobal(), msgId, args);
}
/**
@@ -286,7 +288,7 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException referenceError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException referenceError(final Global global, final String msgId, final String... args) {
return referenceError(global, null, msgId, args);
}
@@ -300,7 +302,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException referenceError(final Throwable cause, final String msgId, final String... args) {
- return referenceError(Context.getGlobalTrusted(), cause, msgId, args);
+ return referenceError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -313,9 +315,9 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException referenceError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException referenceError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("reference.error." + msgId, args);
- return error(((GlobalObject)global).newReferenceError(msg), cause);
+ return error(global.newReferenceError(msg), cause);
}
/**
@@ -327,7 +329,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException uriError(final String msgId, final String... args) {
- return uriError(Context.getGlobalTrusted(), msgId, args);
+ return uriError(Context.getGlobal(), msgId, args);
}
/**
@@ -339,7 +341,7 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException uriError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException uriError(final Global global, final String msgId, final String... args) {
return uriError(global, null, msgId, args);
}
@@ -353,7 +355,7 @@
* @return the resulting {@link ECMAException}
*/
public static ECMAException uriError(final Throwable cause, final String msgId, final String... args) {
- return uriError(Context.getGlobalTrusted(), cause, msgId, args);
+ return uriError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -366,9 +368,9 @@
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException uriError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException uriError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("uri.error." + msgId, args);
- return error(((GlobalObject)global).newURIError(msg), cause);
+ return error(global.newURIError(msg), cause);
}
/**
@@ -401,7 +403,7 @@
final String className = frame.getClassName();
// Look for script package in class name (into which compiler puts generated code)
- if (className.startsWith(scriptPackage)) {
+ if (className.startsWith(scriptPackage) && !frame.getMethodName().startsWith(CompilerConstants.INTERNAL_METHOD_PREFIX)) {
final String source = frame.getFileName();
/*
* Make sure that it is not some Java code that Nashorn has in that package!
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java b/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java
index a32e721..c900963 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java
@@ -25,7 +25,7 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualField;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@@ -44,9 +44,9 @@
@SuppressWarnings("serial")
public final class ECMAException extends NashornException {
/**
- * Method handle pointing to the constructor {@link ECMAException#ECMAException(Object, String, int, int)},
+ * Method handle pointing to the constructor {@link ECMAException#create(Object, String, int, int)},
*/
- public static final Call THROW_INIT = constructorNoLookup(ECMAException.class, Object.class, String.class, int.class, int.class);
+ public static final Call CREATE = staticCallNoLookup(ECMAException.class, "create", ECMAException.class, Object.class, String.class, int.class, int.class);
/** Field handle to the{@link ECMAException#thrown} field, so that it can be accessed from generated code */
public static final FieldAccess THROWN = virtualField(ECMAException.class, "thrown", Object.class);
@@ -57,23 +57,21 @@
public final Object thrown;
/**
- * Constructor. This is called from generated code to implement the {@code throw}
- * instruction from generated script code
+ * Constructor. Called from the factory method 'create'.
*
* @param thrown object to be thrown
* @param fileName script file name
* @param line line number of throw
* @param column column number of throw
*/
- public ECMAException(final Object thrown, final String fileName, final int line, final int column) {
+ private ECMAException(final Object thrown, final String fileName, final int line, final int column) {
super(ScriptRuntime.safeToString(thrown), asThrowable(thrown), fileName, line, column);
this.thrown = thrown;
setExceptionToThrown();
}
/**
- * Constructor. This is called from runtime code in Nashorn to throw things like
- * type errors.
+ * Constructor. This is called from the runtime code.
*
* @param thrown object to be thrown
* @param cause Java exception that triggered this throw
@@ -85,9 +83,39 @@
}
/**
+ * Factory method to retrieve the underlying exception or create an exception.
+ * This method is called from the generated code.
+ *
+ * @param thrown object to be thrown
+ * @param fileName script file name
+ * @param line line number of throw
+ * @param column column number of throw
+ * @return ECMAException object
+ */
+ public static ECMAException create(final Object thrown, final String fileName, final int line, final int column) {
+ // If thrown object is an Error or sub-object like TypeError, then
+ // an ECMAException object has been already initialized at constructor.
+ if (thrown instanceof ScriptObject) {
+ ScriptObject sobj = (ScriptObject)thrown;
+ Object exception = getException(sobj);
+ if (exception instanceof ECMAException) {
+ // copy over file name, line number and column number.
+ final ECMAException ee = (ECMAException)exception;
+ ee.setFileName(fileName);
+ ee.setLineNumber(line);
+ ee.setColumnNumber(column);
+ return ee;
+ }
+ }
+
+ return new ECMAException(thrown, fileName, line, column);
+ }
+
+ /**
* Get the thrown object
* @return thrown object
*/
+ @Override
public Object getThrown() {
return thrown;
}
@@ -256,6 +284,8 @@
final ScriptObject sobj = (ScriptObject)thrown;
if (!sobj.has(EXCEPTION_PROPERTY)) {
sobj.addOwnProperty(EXCEPTION_PROPERTY, Property.NOT_ENUMERABLE, this);
+ } else {
+ sobj.set(EXCEPTION_PROPERTY, this, false);
}
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
index c7a410e..f16cf41 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
@@ -38,31 +38,27 @@
/**
* Constructor - used for bind
*
- * @param name name
- * @param arity arity
- * @param functions precompiled code
- * @param isStrict strict
- * @param isBuiltin builtin
- * @param isConstructor constructor
+ * @param name name
+ * @param arity arity
+ * @param functions precompiled code
+ * @param flags {@link ScriptFunctionData} flags
*/
- FinalScriptFunctionData(final String name, int arity, CompiledFunctions functions, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
- super(name, arity, isStrict, isBuiltin, isConstructor);
+ FinalScriptFunctionData(final String name, final int arity, final CompiledFunctions functions, final int flags) {
+ super(name, arity, flags);
code.addAll(functions);
}
/**
- * Constructor - used from ScriptFunction. This assumes that we have code alraedy for the
+ * Constructor - used from ScriptFunction. This assumes that we have code already for the
* method (typically a native method) and possibly specializations.
*
- * @param name name
- * @param mh method handle for generic version of method
- * @param specs specializations
- * @param isStrict strict
- * @param isBuiltin builtin
- * @param isConstructor constructor
+ * @param name name
+ * @param mh method handle for generic version of method
+ * @param specs specializations
+ * @param flags {@link ScriptFunctionData} flags
*/
- FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
- super(name, arity(mh), isStrict, isBuiltin, isConstructor);
+ FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final int flags) {
+ super(name, arity(mh), flags);
addInvoker(mh);
if (specs != null) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java b/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java
index c14accb..87a8c74 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java
@@ -112,7 +112,7 @@
return property != null && property.hasGetterFunction(prototype) ? self : prototype;
}
- /**
+ /**
* Return the appropriate receiver for a setter.
* @return appropriate receiver
*/
@@ -172,5 +172,20 @@
property.setObjectValue(getSetterReceiver(), getOwner(), value, strict);
}
+ /**
+ * Get the number of objects in the prototype chain between the {@code self} and the
+ * {@code owner} objects.
+ * @return the prototype chain length
+ */
+ int getProtoChainLength() {
+ assert self != null;
+ int length = 0;
+ for (ScriptObject obj = self; obj != prototype; obj = obj.getProto()) {
+ assert !(obj instanceof WithObject);
+ ++length;
+ }
+ return length;
+ }
+
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java b/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java
deleted file mode 100644
index 3779f3b..0000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, 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 jdk.nashorn.internal.runtime;
-
-import java.lang.invoke.MethodHandle;
-import java.util.concurrent.Callable;
-import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.LinkRequest;
-import jdk.nashorn.internal.runtime.linker.InvokeByName;
-
-/**
- * Runtime interface to the global scope objects.
- */
-
-public interface GlobalObject {
- /**
- * Is this global of the given Context?
- * @param ctxt the context
- * @return true if this global belongs to the given Context
- */
- public boolean isOfContext(final Context ctxt);
-
- /**
- * Does this global belong to a strict Context?
- * @return true if this global belongs to a strict Context
- */
- public boolean isStrictContext();
-
- /**
- * Initialize standard builtin objects like "Object", "Array", "Function" etc.
- * as well as our extension builtin objects like "Java", "JSAdapter" as properties
- * of the global scope object.
- */
- public void initBuiltinObjects();
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newScriptFunction(String, MethodHandle, ScriptObject, boolean)}
- *
- * @param name function name
- * @param handle invocation handle for function
- * @param scope the scope
- * @param strict are we in strict mode
- *
- * @return new script function
- */
- public ScriptFunction newScriptFunction(String name, MethodHandle handle, ScriptObject scope, boolean strict);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#wrapAsObject(Object)}
- *
- * @param obj object to wrap
- * @return wrapped object
- */
- public Object wrapAsObject(Object obj);
-
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#primitiveLookup(LinkRequest, Object)}
- *
- * @param request the link request for the dynamic call site.
- * @param self self reference
- *
- * @return guarded invocation
- */
- public GuardedInvocation primitiveLookup(LinkRequest request, Object self);
-
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newObject()}
- *
- * @return the new ScriptObject
- */
- public ScriptObject newObject();
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#isError(ScriptObject)}
- *
- * @param sobj to check if it is an error object
- * @return true if error object
- */
- public boolean isError(ScriptObject sobj);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the error
- */
- public ScriptObject newError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newEvalError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the eval error
- */
- public ScriptObject newEvalError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newRangeError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the range error
- */
- public ScriptObject newRangeError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newReferenceError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the reference error
- */
- public ScriptObject newReferenceError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newSyntaxError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the syntax error
- */
- public ScriptObject newSyntaxError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newTypeError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the type error
- */
- public ScriptObject newTypeError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newURIError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the URI error
- */
- public ScriptObject newURIError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newGenericDescriptor(boolean, boolean)}
- *
- * @param configurable is the described property configurable
- * @param enumerable is the described property enumerable
- *
- * @return property descriptor
- */
- public PropertyDescriptor newGenericDescriptor(boolean configurable, boolean enumerable);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newDataDescriptor(Object, boolean, boolean, boolean)}
- *
- * @param value data value
- * @param configurable is the described property configurable
- * @param enumerable is the described property enumerable
- * @param writable is the described property writable
- *
- * @return property descriptor
- */
- public PropertyDescriptor newDataDescriptor(Object value, boolean configurable, boolean enumerable, boolean writable);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newAccessorDescriptor(Object, Object, boolean, boolean)}
- *
- * @param get property getter, or null if none
- * @param set property setter, or null if none
- * @param configurable is the described property configurable
- * @param enumerable is the described property enumerable
- *
- * @return property descriptor
- */
- public PropertyDescriptor newAccessorDescriptor(Object get, Object set, boolean configurable, boolean enumerable);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#getDefaultValue(ScriptObject, Class)}
- *
- * @param sobj script object
- * @param typeHint type hint
- *
- * @return default value
- */
- public Object getDefaultValue(ScriptObject sobj, Class<?> typeHint);
-
- /**
- * Find the compiled Class for the given script source, if available
- *
- * @param source Source object of the script
- * @return compiled Class object or null
- */
- public Class<?> findCachedClass(Source source);
-
- /**
- * Put the Source associated Class object in the Source-to-Class cache
- *
- * @param source Source of the script
- * @param clazz compiled Class object for the source
- */
- public void cacheClass(Source source, Class<?> clazz);
-
- /**
- * Get cached InvokeByName object for the given key
- * @param key key to be associated with InvokeByName object
- * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
- * @return InvokeByName object associated with the key.
- */
- public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator);
-
- /**
- * Get cached dynamic method handle for the given key
- * @param key key to be associated with dynamic method handle
- * @param creator if method handle is absent 'creator' is called to make one (lazy init)
- * @return dynamic method handle associated with the key.
- */
- public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator);
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java
index 73552cb..f12945f 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java
@@ -33,6 +33,7 @@
import jdk.nashorn.internal.ir.ObjectNode;
import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.JSONParser;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
@@ -47,7 +48,7 @@
private static final Object REVIVER_INVOKER = new Object();
private static MethodHandle getREVIVER_INVOKER() {
- return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(REVIVER_INVOKER,
+ return Context.getGlobal().getDynamicInvoker(REVIVER_INVOKER,
new Callable<MethodHandle>() {
@Override
public MethodHandle call() {
@@ -88,7 +89,7 @@
throw ECMAErrors.syntaxError(e, "invalid.json", e.getMessage());
}
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
Object unfiltered = convertNode(global, node);
return applyReviver(global, unfiltered, reviver);
}
@@ -98,10 +99,9 @@
// parse helpers
// apply 'reviver' function if available
- private static Object applyReviver(final ScriptObject global, final Object unfiltered, final Object reviver) {
+ private static Object applyReviver(final Global global, final Object unfiltered, final Object reviver) {
if (reviver instanceof ScriptFunction) {
- assert global instanceof GlobalObject;
- final ScriptObject root = ((GlobalObject)global).newObject();
+ final ScriptObject root = global.newObject();
root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered);
return walk(root, "", (ScriptFunction)reviver);
}
@@ -138,8 +138,8 @@
}
// Converts IR node to runtime value
- private static Object convertNode(final ScriptObject global, final Node node) {
- assert global instanceof GlobalObject;
+ private static Object convertNode(final Global global, final Node node) {
+ assert global instanceof Global;
if (node instanceof LiteralNode) {
// check for array literal
@@ -157,7 +157,7 @@
for (final Node elem : elements) {
values[index++] = JSType.toNumber(convertNode(global, elem));
}
- return ((GlobalObject)global).wrapAsObject(values);
+ return global.wrapAsObject(values);
}
final Object[] values = new Object[elements.length];
@@ -167,14 +167,14 @@
values[index++] = convertNode(global, elem);
}
- return ((GlobalObject)global).wrapAsObject(values);
+ return global.wrapAsObject(values);
}
return ((LiteralNode<?>)node).getValue();
} else if (node instanceof ObjectNode) {
final ObjectNode objNode = (ObjectNode) node;
- final ScriptObject object = ((GlobalObject)global).newObject();
+ final ScriptObject object = global.newObject();
for (final PropertyNode pNode: objNode.getElements()) {
final Node valueNode = pNode.getValue();
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
index 5413019..c49de9c 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
@@ -36,6 +36,7 @@
import jdk.internal.dynalink.beans.StaticClass;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Lexer;
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -852,7 +853,7 @@
* @return the wrapped object
*/
public static Object toScriptObject(final Object obj) {
- return toScriptObject(Context.getGlobalTrusted(), obj);
+ return toScriptObject(Context.getGlobal(), obj);
}
/**
@@ -865,7 +866,7 @@
*
* @return the wrapped object
*/
- public static Object toScriptObject(final ScriptObject global, final Object obj) {
+ public static Object toScriptObject(final Global global, final Object obj) {
if (nullOrUndefined(obj)) {
throw typeError(global, "not.an.object", ScriptRuntime.safeToString(obj));
}
@@ -874,7 +875,7 @@
return obj;
}
- return ((GlobalObject)global).wrapAsObject(obj);
+ return global.wrapAsObject(obj);
}
/**
@@ -984,7 +985,7 @@
if (obj instanceof ScriptObject) {
if (safe) {
final ScriptObject sobj = (ScriptObject)obj;
- final GlobalObject gobj = (GlobalObject)Context.getGlobalTrusted();
+ final Global gobj = Context.getGlobal();
return gobj.isError(sobj) ?
ECMAException.safeToString(sobj) :
sobj.safeToString();
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
index 26c22c3..9a3408f 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
@@ -34,6 +34,7 @@
import java.util.concurrent.Callable;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
@@ -54,7 +55,7 @@
// These add to the back and front of the list
private static final Object PUSH = new Object();
private static InvokeByName getPUSH() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(PUSH,
+ return Context.getGlobal().getInvokeByName(PUSH,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -65,7 +66,7 @@
private static final Object UNSHIFT = new Object();
private static InvokeByName getUNSHIFT() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(UNSHIFT,
+ return Context.getGlobal().getInvokeByName(UNSHIFT,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -77,7 +78,7 @@
// These remove from the back and front of the list
private static final Object POP = new Object();
private static InvokeByName getPOP() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(POP,
+ return Context.getGlobal().getInvokeByName(POP,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -88,7 +89,7 @@
private static final Object SHIFT = new Object();
private static InvokeByName getSHIFT() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(SHIFT,
+ return Context.getGlobal().getInvokeByName(SHIFT,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -100,7 +101,7 @@
// These insert and remove in the middle of the list
private static final Object SPLICE_ADD = new Object();
private static InvokeByName getSPLICE_ADD() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(SPLICE_ADD,
+ return Context.getGlobal().getInvokeByName(SPLICE_ADD,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -111,7 +112,7 @@
private static final Object SPLICE_REMOVE = new Object();
private static InvokeByName getSPLICE_REMOVE() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(SPLICE_REMOVE,
+ return Context.getGlobal().getInvokeByName(SPLICE_REMOVE,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
index 534d495..fbca1c3 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
@@ -35,7 +35,6 @@
import jdk.internal.dynalink.support.Guards;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
-import jdk.nashorn.internal.objects.NativeJava;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -52,7 +51,7 @@
* var ArrayList = java.util.ArrayList
* var list = new ArrayList
* </pre>
- * You can also use {@link NativeJava#type(Object, Object)} to access Java classes. These two statements are mostly
+ * You can also use {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)} to access Java classes. These two statements are mostly
* equivalent:
* <pre>
* var listType1 = java.util.ArrayList
@@ -198,27 +197,16 @@
@Override
public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) {
final String propertyName = desc.getNameToken(2);
- final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName;
-
- final Context context = Context.getContextTrusted();
-
- Class<?> javaClass = null;
- try {
- javaClass = context.findClass(fullName);
- } catch (final NoClassDefFoundError | ClassNotFoundException e) {
- //ignored
- }
-
- if (javaClass == null) {
- set(propertyName, new NativeJavaPackage(fullName, getProto()), false);
- } else {
- set(propertyName, StaticClass.forClass(javaClass), false);
- }
-
+ createProperty(propertyName);
return super.lookup(desc, request);
}
@Override
+ protected Object invokeNoSuchProperty(final String name) {
+ return createProperty(name);
+ }
+
+ @Override
public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return noSuchProperty(desc, request);
}
@@ -226,4 +214,26 @@
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(MethodHandles.lookup(), NativeJavaPackage.class, name, MH.type(rtype, types));
}
+
+ private Object createProperty(final String propertyName) {
+ final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName;
+ final Context context = Context.getContextTrusted();
+
+ Class<?> javaClass = null;
+ try {
+ javaClass = context.findClass(fullName);
+ } catch (final NoClassDefFoundError | ClassNotFoundException e) {
+ //ignored
+ }
+
+ final Object propertyValue;
+ if (javaClass == null) {
+ propertyValue = new NativeJavaPackage(fullName, getProto());
+ } else {
+ propertyValue = StaticClass.forClass(javaClass);
+ }
+
+ set(propertyName, propertyValue, false);
+ return propertyValue;
+ }
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ParserException.java b/nashorn/src/jdk/nashorn/internal/runtime/ParserException.java
index 2424bc3..5137d59 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ParserException.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ParserException.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime;
import jdk.nashorn.api.scripting.NashornException;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Token;
/**
@@ -110,7 +111,7 @@
* Throw this {@code ParserException} as one of the 7 native JavaScript errors
* @param global global scope object
*/
- public void throwAsEcmaException(final ScriptObject global) {
+ public void throwAsEcmaException(final Global global) {
throw ECMAErrors.asEcmaException(global, this);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Property.java b/nashorn/src/jdk/nashorn/internal/runtime/Property.java
index d1dbe2a..885fa71 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/Property.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java
@@ -84,9 +84,13 @@
/** Can this property be undefined? */
public static final int CAN_BE_UNDEFINED = 1 << 8;
- /* Is this a function declaration property ? */
+ /** Is this a function declaration property ? */
public static final int IS_FUNCTION_DECLARATION = 1 << 9;
+ /** Is this property bound to a receiver? This means get/set operations will be delegated to
+ * a statically defined object instead of the object passed as callsite parameter. */
+ public static final int IS_BOUND = 1 << 10;
+
/** Property key. */
private final String key;
@@ -252,6 +256,16 @@
}
/**
+ * Is this property bound to a receiver? If this method returns {@code true} get and set operations
+ * will be delegated to a statically bound object instead of the object passed as parameter.
+ *
+ * @return true if this is a bound property
+ */
+ public boolean isBound() {
+ return (flags & IS_BOUND) == IS_BOUND;
+ }
+
+ /**
* Does this property use any slots in the spill array described in
* {@link Property#isSpill}? In that case how many. Currently a property
* only uses max one spill slot, but this may change in future representations
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
index 49a7a9d..f36bd45 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
@@ -151,5 +151,12 @@
* @return true if property exists in implementor
*/
public boolean has(Object key);
+
+ /**
+ * Check existence and compare attributes of descriptors.
+ *
+ * @return true if every field of this desc exists in otherDesc and has the same value.
+ */
+ public boolean hasAndEquals(PropertyDescriptor otherDesc);
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java
deleted file mode 100644
index 307d58b..0000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, 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 jdk.nashorn.internal.runtime;
-
-/**
- * Property change listener gets notified whenever properties are added/deleted/modified.
- */
-public interface PropertyListener {
- /**
- * A new property is being added.
- *
- * @param object The ScriptObject to which property was added.
- * @param prop The new Property added.
- */
- public void propertyAdded(ScriptObject object, Property prop);
-
- /**
- * An existing property is being deleted.
- *
- * @param object The ScriptObject whose property is being deleted.
- * @param prop The property being deleted.
- */
- public void propertyDeleted(ScriptObject object, Property prop);
-
- /**
- * An existing Property is being replaced with a new Property.
- *
- * @param object The ScriptObject whose property is being modified.
- * @param oldProp The old property that is being replaced.
- * @param newProp The new property that replaces the old property.
- *
- */
- public void propertyModified(ScriptObject object, Property oldProp, Property newProp);
-
- /**
- * Given object's __proto__ has changed.
- *
- * @param object object whose __proto__ has changed.
- * @param oldProto old __proto__
- * @param newProto new __proto__
- */
- public void protoChanged(ScriptObject object, ScriptObject oldProto, ScriptObject newProto);
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java
deleted file mode 100644
index 27ec2c9..0000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, 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 jdk.nashorn.internal.runtime;
-
-import java.util.Map;
-import java.util.WeakHashMap;
-
-/**
- * Helper class to manage property listeners and notification.
- */
-public class PropertyListenerManager implements PropertyListener {
- PropertyListenerManager() {}
-
- /** property listeners for this object. */
- private Map<PropertyListener,Boolean> listeners;
-
- // These counters are updated in debug mode
- private static int listenersAdded;
- private static int listenersRemoved;
-
- /**
- * Return aggregate listeners added to all PropertyListenerManagers
- * @return the listenersAdded
- */
- public static int getListenersAdded() {
- return listenersAdded;
- }
-
- /**
- * Return aggregate listeners removed from all PropertyListenerManagers
- * @return the listenersRemoved
- */
- public static int getListenersRemoved() {
- return listenersRemoved;
- }
-
- /**
- * Return listeners added to this PropertyListenerManager.
- * @return the listener count
- */
- public final int getListenerCount() {
- return listeners != null? listeners.size() : 0;
- }
-
- // Property listener management methods
-
- /**
- * Add a property listener to this object.
- *
- * @param listener The property listener that is added.
- */
- public synchronized final void addPropertyListener(final PropertyListener listener) {
- if (listeners == null) {
- listeners = new WeakHashMap<>();
- }
-
- if (Context.DEBUG) {
- listenersAdded++;
- }
- listeners.put(listener, Boolean.TRUE);
- }
-
- /**
- * Remove a property listener from this object.
- *
- * @param listener The property listener that is removed.
- */
- public synchronized final void removePropertyListener(final PropertyListener listener) {
- if (listeners != null) {
- if (Context.DEBUG) {
- listenersRemoved++;
- }
- listeners.remove(listener);
- }
- }
-
- /**
- * This method can be called to notify property addition to this object's listeners.
- *
- * @param object The ScriptObject to which property was added.
- * @param prop The property being added.
- */
- protected synchronized final void notifyPropertyAdded(final ScriptObject object, final Property prop) {
- if (listeners != null) {
- for (PropertyListener listener : listeners.keySet()) {
- listener.propertyAdded(object, prop);
- }
- }
- }
-
- /**
- * This method can be called to notify property deletion to this object's listeners.
- *
- * @param object The ScriptObject from which property was deleted.
- * @param prop The property being deleted.
- */
- protected synchronized final void notifyPropertyDeleted(final ScriptObject object, final Property prop) {
- if (listeners != null) {
- for (PropertyListener listener : listeners.keySet()) {
- listener.propertyDeleted(object, prop);
- }
- }
- }
-
- /**
- * This method can be called to notify property modification to this object's listeners.
- *
- * @param object The ScriptObject to which property was modified.
- * @param oldProp The old property being replaced.
- * @param newProp The new property that replaces the old property.
- */
- protected synchronized final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
- if (listeners != null) {
- for (PropertyListener listener : listeners.keySet()) {
- listener.propertyModified(object, oldProp, newProp);
- }
- }
- }
-
- /**
- * This method can be called to notify __proto__ modification to this object's listeners.
- *
- * @param object The ScriptObject whose __proto__ was changed.
- * @param oldProto old __proto__
- * @param newProto new __proto__
- */
- protected synchronized final void notifyProtoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
- if (listeners != null) {
- for (PropertyListener listener : listeners.keySet()) {
- listener.protoChanged(object, oldProto, newProto);
- }
- }
- }
-
- // PropertyListener methods
-
- @Override
- public final void propertyAdded(final ScriptObject object, final Property prop) {
- notifyPropertyAdded(object, prop);
- }
-
- @Override
- public final void propertyDeleted(final ScriptObject object, final Property prop) {
- notifyPropertyDeleted(object, prop);
- }
-
- @Override
- public final void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
- notifyPropertyModified(object, oldProp, newProp);
- }
-
- @Override
- public final void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
- notifyProtoChanged(object, oldProto, newProto);
- }
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java
new file mode 100644
index 0000000..532969c
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2010, 2014, 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 jdk.nashorn.internal.runtime;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * Helper class to manage property listeners and notification.
+ */
+public class PropertyListeners {
+
+ private Map<String, WeakPropertyMapSet> listeners;
+
+ // These counters are updated in debug mode
+ private static int listenersAdded;
+ private static int listenersRemoved;
+
+ /**
+ * Copy constructor
+ * @param listener listener to copy
+ */
+ PropertyListeners(final PropertyListeners listener) {
+ if (listener != null && listener.listeners != null) {
+ this.listeners = new WeakHashMap<>(listener.listeners);
+ }
+ }
+
+ /**
+ * Return aggregate listeners added to all PropertyListenerManagers
+ * @return the listenersAdded
+ */
+ public static int getListenersAdded() {
+ return listenersAdded;
+ }
+
+ /**
+ * Return aggregate listeners removed from all PropertyListenerManagers
+ * @return the listenersRemoved
+ */
+ public static int getListenersRemoved() {
+ return listenersRemoved;
+ }
+
+ /**
+ * Return listeners added to this ScriptObject.
+ * @param obj the object
+ * @return the listener count
+ */
+ public static int getListenerCount(final ScriptObject obj) {
+ final PropertyListeners propertyListeners = obj.getMap().getListeners();
+ if (propertyListeners != null) {
+ return propertyListeners.listeners == null ? 0 : propertyListeners.listeners.size();
+ }
+ return 0;
+ }
+
+ // Property listener management methods
+
+ /**
+ * Add {@code propertyMap} as property listener to {@code listeners} using key {@code key} by
+ * creating and returning a new {@code PropertyListeners} instance.
+ *
+ * @param listeners the original property listeners instance, may be null
+ * @param key the property key
+ * @param propertyMap the property map
+ * @return the new property map
+ */
+ public static PropertyListeners addListener(final PropertyListeners listeners, final String key, final PropertyMap propertyMap) {
+ final PropertyListeners newListeners;
+ if (listeners == null || !listeners.containsListener(key, propertyMap)) {
+ newListeners = new PropertyListeners(listeners);
+ newListeners.addListener(key, propertyMap);
+ return newListeners;
+ }
+ return listeners;
+ }
+
+ /**
+ * Checks whether {@code propertyMap} is registered as listener with {@code key}.
+ *
+ * @param key the property key
+ * @param propertyMap the property map
+ * @return true if property map is registered with property key
+ */
+ synchronized boolean containsListener(final String key, final PropertyMap propertyMap) {
+ if (listeners == null) {
+ return false;
+ }
+ WeakPropertyMapSet set = listeners.get(key);
+ return set != null && set.contains(propertyMap);
+ }
+
+ /**
+ * Add a property listener to this object.
+ *
+ * @param propertyMap The property listener that is added.
+ */
+ synchronized final void addListener(final String key, final PropertyMap propertyMap) {
+ if (Context.DEBUG) {
+ listenersAdded++;
+ }
+ if (listeners == null) {
+ listeners = new WeakHashMap<>();
+ }
+
+ WeakPropertyMapSet set = listeners.get(key);
+ if (set == null) {
+ set = new WeakPropertyMapSet();
+ listeners.put(key, set);
+ }
+ if (!set.contains(propertyMap)) {
+ set.add(propertyMap);
+ }
+ }
+
+ /**
+ * A new property is being added.
+ *
+ * @param prop The new Property added.
+ */
+ public synchronized void propertyAdded(final Property prop) {
+ if (listeners != null) {
+ WeakPropertyMapSet set = listeners.get(prop.getKey());
+ if (set != null) {
+ for (PropertyMap propertyMap : set.elements()) {
+ propertyMap.propertyAdded(prop);
+ }
+ listeners.remove(prop.getKey());
+ }
+ }
+ }
+
+ /**
+ * An existing property is being deleted.
+ *
+ * @param prop The property being deleted.
+ */
+ public synchronized void propertyDeleted(final Property prop) {
+ if (listeners != null) {
+ WeakPropertyMapSet set = listeners.get(prop.getKey());
+ if (set != null) {
+ for (PropertyMap propertyMap : set.elements()) {
+ propertyMap.propertyDeleted(prop);
+ }
+ listeners.remove(prop.getKey());
+ }
+ }
+ }
+
+ /**
+ * An existing Property is being replaced with a new Property.
+ *
+ * @param oldProp The old property that is being replaced.
+ * @param newProp The new property that replaces the old property.
+ *
+ */
+ public synchronized void propertyModified(final Property oldProp, final Property newProp) {
+ if (listeners != null) {
+ WeakPropertyMapSet set = listeners.get(oldProp.getKey());
+ if (set != null) {
+ for (PropertyMap propertyMap : set.elements()) {
+ propertyMap.propertyModified(oldProp, newProp);
+ }
+ listeners.remove(oldProp.getKey());
+ }
+ }
+ }
+
+ public synchronized void protoChanged() {
+ if (listeners != null) {
+ for (WeakPropertyMapSet set : listeners.values()) {
+ for (PropertyMap propertyMap : set.elements()) {
+ propertyMap.protoChanged();
+ }
+ }
+ listeners.clear();
+ }
+ }
+
+ private static class WeakPropertyMapSet {
+
+ private WeakHashMap<PropertyMap, Boolean> map = new WeakHashMap<>();
+
+ void add(final PropertyMap propertyMap) {
+ map.put(propertyMap, Boolean.TRUE);
+ }
+
+ boolean contains(final PropertyMap propertyMap) {
+ return map.containsKey(propertyMap);
+ }
+
+ Set<PropertyMap> elements() {
+ return map.keySet();
+ }
+
+ }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java
index 03c4978..77bcc83 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java
@@ -30,13 +30,11 @@
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import java.lang.invoke.SwitchPoint;
-import java.lang.ref.WeakReference;
+import java.lang.ref.SoftReference;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
import java.util.NoSuchElementException;
import java.util.WeakHashMap;
@@ -49,17 +47,11 @@
* All property maps are immutable. If a property is added, modified or removed, the mutator
* will return a new map.
*/
-public final class PropertyMap implements Iterable<Object>, PropertyListener {
+public final class PropertyMap implements Iterable<Object> {
/** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
public static final int NOT_EXTENSIBLE = 0b0000_0001;
/** Does this map contain valid array keys? */
public static final int CONTAINS_ARRAY_KEYS = 0b0000_0010;
- /** This mask is used to preserve certain flags when cloning the PropertyMap. Others should not be copied */
- private static final int CLONEABLE_FLAGS_MASK = 0b0000_1111;
- /** Has a listener been added to this property map. This flag is not copied when cloning a map. See {@link PropertyListener} */
- public static final int IS_LISTENER_ADDED = 0b0001_0000;
- /** Is this process wide "shared" map?. This flag is not copied when cloning a map */
- public static final int IS_SHARED = 0b0010_0000;
/** Map status flags. */
private int flags;
@@ -77,16 +69,16 @@
private int spillLength;
/** {@link SwitchPoint}s for gets on inherited properties. */
- private Map<String, SwitchPoint> protoGetSwitches;
+ private HashMap<String, SwitchPoint> protoGetSwitches;
/** History of maps, used to limit map duplication. */
- private HashMap<Property, PropertyMap> history;
+ private WeakHashMap<Property, SoftReference<PropertyMap>> history;
/** History of prototypes, used to limit map duplication. */
- private WeakHashMap<ScriptObject, WeakReference<PropertyMap>> protoHistory;
+ private WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
- /** Cache for hashCode */
- private int hashCode;
+ /** property listeners */
+ private PropertyListeners listeners;
/**
* Constructor.
@@ -119,10 +111,12 @@
*/
private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
this.properties = properties;
- this.flags = propertyMap.getClonedFlags();
+ this.flags = propertyMap.flags;
this.spillLength = propertyMap.spillLength;
this.fieldCount = propertyMap.fieldCount;
this.fieldMaximum = propertyMap.fieldMaximum;
+ // We inherit the parent property listeners instance. It will be cloned when a new listener is added.
+ this.listeners = propertyMap.listeners;
if (Context.DEBUG) {
count++;
@@ -203,35 +197,92 @@
}
/**
+ * Get the listeners of this map, or null if none exists
+ *
+ * @return the listeners
+ */
+ public PropertyListeners getListeners() {
+ return listeners;
+ }
+
+ /**
+ * Add {@code listenerMap} as a listener to this property map for the given {@code key}.
+ *
+ * @param key the property name
+ * @param listenerMap the listener map
+ */
+ public void addListener(final String key, final PropertyMap listenerMap) {
+ if (listenerMap != this) {
+ // We need to clone listener instance when adding a new listener since we share
+ // the listeners instance with our parent maps that don't need to see the new listener.
+ listeners = PropertyListeners.addListener(listeners, key, listenerMap);
+ }
+ }
+
+ /**
+ * A new property is being added.
+ *
+ * @param property The new Property added.
+ */
+ public void propertyAdded(final Property property) {
+ invalidateProtoGetSwitchPoint(property);
+ if (listeners != null) {
+ listeners.propertyAdded(property);
+ }
+ }
+
+ /**
+ * An existing property is being deleted.
+ *
+ * @param property The property being deleted.
+ */
+ public void propertyDeleted(final Property property) {
+ invalidateProtoGetSwitchPoint(property);
+ if (listeners != null) {
+ listeners.propertyDeleted(property);
+ }
+ }
+
+ /**
+ * An existing property is being redefined.
+ *
+ * @param oldProperty The old property
+ * @param newProperty The new property
+ */
+ public void propertyModified(final Property oldProperty, final Property newProperty) {
+ invalidateProtoGetSwitchPoint(oldProperty);
+ if (listeners != null) {
+ listeners.propertyModified(oldProperty, newProperty);
+ }
+ }
+
+ /**
+ * The prototype of an object associated with this {@link PropertyMap} is changed.
+ */
+ public void protoChanged() {
+ invalidateAllProtoGetSwitchPoints();
+ if (listeners != null) {
+ listeners.protoChanged();
+ }
+ }
+
+ /**
* Return a SwitchPoint used to track changes of a property in a prototype.
*
- * @param proto Object prototype.
- * @param key {@link Property} key.
- *
+ * @param key Property key.
* @return A shared {@link SwitchPoint} for the property.
*/
- public SwitchPoint getProtoGetSwitchPoint(final ScriptObject proto, final String key) {
- assert !isShared() : "proto SwitchPoint from a shared PropertyMap";
-
- if (proto == null) {
- return null;
- }
-
+ public synchronized SwitchPoint getSwitchPoint(final String key) {
if (protoGetSwitches == null) {
protoGetSwitches = new HashMap<>();
- if (! isListenerAdded()) {
- proto.addPropertyListener(this);
- setIsListenerAdded();
- }
}
- if (protoGetSwitches.containsKey(key)) {
- return protoGetSwitches.get(key);
+ SwitchPoint switchPoint = protoGetSwitches.get(key);
+ if (switchPoint == null) {
+ switchPoint = new SwitchPoint();
+ protoGetSwitches.put(key, switchPoint);
}
- final SwitchPoint switchPoint = new SwitchPoint();
- protoGetSwitches.put(key, switchPoint);
-
return switchPoint;
}
@@ -240,14 +291,13 @@
*
* @param property {@link Property} to invalidate.
*/
- private void invalidateProtoGetSwitchPoint(final Property property) {
- assert !isShared() : "proto invalidation on a shared PropertyMap";
-
+ synchronized void invalidateProtoGetSwitchPoint(final Property property) {
if (protoGetSwitches != null) {
+
final String key = property.getKey();
final SwitchPoint sp = protoGetSwitches.get(key);
if (sp != null) {
- protoGetSwitches.put(key, new SwitchPoint());
+ protoGetSwitches.remove(key);
if (Context.DEBUG) {
protoInvalidations++;
}
@@ -257,14 +307,15 @@
}
/**
- * Indicate that proto itself has changed in hierachy somewhere.
+ * Indicate that proto itself has changed in hierarchy somewhere.
*/
- private void invalidateAllProtoGetSwitchPoints() {
- assert !isShared() : "proto invalidation on a shared PropertyMap";
-
- if (protoGetSwitches != null) {
- final Collection<SwitchPoint> sws = protoGetSwitches.values();
- SwitchPoint.invalidateAll(sws.toArray(new SwitchPoint[sws.size()]));
+ synchronized void invalidateAllProtoGetSwitchPoints() {
+ if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) {
+ if (Context.DEBUG) {
+ protoInvalidations += protoGetSwitches.size();
+ }
+ SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()]));
+ protoGetSwitches.clear();
}
}
@@ -279,7 +330,33 @@
* @return New {@link PropertyMap} with {@link Property} added.
*/
PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
- return addProperty(new AccessorProperty(property, bindTo));
+ // No need to store bound property in the history as bound properties can't be reused.
+ return addPropertyNoHistory(new AccessorProperty(property, bindTo));
+ }
+
+ /**
+ * Add a property to the map without adding it to the history. This should be used for properties that
+ * can't be shared such as bound properties, or properties that are expected to be added only once.
+ *
+ * @param property {@link Property} being added.
+ * @return New {@link PropertyMap} with {@link Property} added.
+ */
+ public PropertyMap addPropertyNoHistory(final Property property) {
+ if (listeners != null) {
+ listeners.propertyAdded(property);
+ }
+ final PropertyHashMap newProperties = properties.immutableAdd(property);
+ final PropertyMap newMap = new PropertyMap(this, newProperties);
+
+ if(!property.isSpill()) {
+ newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
+ }
+ if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
+ newMap.setContainsArrayKeys();
+ }
+
+ newMap.spillLength += property.getSpillCount();
+ return newMap;
}
/**
@@ -290,6 +367,9 @@
* @return New {@link PropertyMap} with {@link Property} added.
*/
public PropertyMap addProperty(final Property property) {
+ if (listeners != null) {
+ listeners.propertyAdded(property);
+ }
PropertyMap newMap = checkHistory(property);
if (newMap == null) {
@@ -318,6 +398,9 @@
* @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found.
*/
public PropertyMap deleteProperty(final Property property) {
+ if (listeners != null) {
+ listeners.propertyDeleted(property);
+ }
PropertyMap newMap = checkHistory(property);
final String key = property.getKey();
@@ -339,6 +422,9 @@
* @return New {@link PropertyMap} with {@link Property} replaced.
*/
PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
+ if (listeners != null) {
+ listeners.propertyModified(oldProperty, newProperty);
+ }
// Add replaces existing property.
final PropertyHashMap newProperties = properties.immutableAdd(newProperty);
final PropertyMap newMap = new PropertyMap(this, newProperties);
@@ -363,7 +449,7 @@
(oldProperty instanceof AccessorProperty &&
newProperty instanceof UserAccessorProperty) : "arbitrary replaceProperty attempted";
- newMap.flags = getClonedFlags();
+ newMap.flags = flags;
/*
* spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
@@ -491,28 +577,6 @@
}
/**
- * Make this property map 'shared' one. Shared property map instances are
- * process wide singleton objects. A shaped map should never be added as a listener
- * to a proto object. Nor it should have history or proto history. A shared map
- * is just a template that is meant to be duplicated before use. All nasgen initialized
- * property maps are shared.
- *
- * @return this map after making it as shared
- */
- public PropertyMap setIsShared() {
- assert !isListenerAdded() : "making PropertyMap shared after listener added";
- assert protoHistory == null : "making PropertyMap shared after associating a proto with it";
- if (Context.DEBUG) {
- sharedCount++;
- }
-
- flags |= IS_SHARED;
- // clear any history on this PropertyMap, won't be used.
- history = null;
- return this;
- }
-
- /**
* Check for any configurable properties.
*
* @return {@code true} if any configurable.
@@ -551,14 +615,14 @@
/**
* Check prototype history for an existing property map with specified prototype.
*
- * @param newProto New prototype object.
+ * @param parentMap New prototype object.
*
* @return Existing {@link PropertyMap} or {@code null} if not found.
*/
- private PropertyMap checkProtoHistory(final ScriptObject newProto) {
+ private PropertyMap checkProtoHistory(final PropertyMap parentMap) {
final PropertyMap cachedMap;
if (protoHistory != null) {
- final WeakReference<PropertyMap> weakMap = protoHistory.get(newProto);
+ final SoftReference<PropertyMap> weakMap = protoHistory.get(parentMap);
cachedMap = (weakMap != null ? weakMap.get() : null);
} else {
cachedMap = null;
@@ -574,17 +638,15 @@
/**
* Add a map to the prototype history.
*
- * @param newProto Prototype to add (key.)
+ * @param parentMap Prototype to add (key.)
* @param newMap {@link PropertyMap} associated with prototype.
*/
- private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
- assert !isShared() : "proto history modified on a shared PropertyMap";
-
+ private void addToProtoHistory(final PropertyMap parentMap, final PropertyMap newMap) {
if (protoHistory == null) {
protoHistory = new WeakHashMap<>();
}
- protoHistory.put(newProto, new WeakReference<>(newMap));
+ protoHistory.put(parentMap, new SoftReference<>(newMap));
}
/**
@@ -594,14 +656,12 @@
* @param newMap Modified {@link PropertyMap}.
*/
private void addToHistory(final Property property, final PropertyMap newMap) {
- assert !isShared() : "history modified on a shared PropertyMap";
-
if (!properties.isEmpty()) {
if (history == null) {
- history = new LinkedHashMap<>();
+ history = new WeakHashMap<>();
}
- history.put(property, newMap);
+ history.put(property, new SoftReference<>(newMap));
}
}
@@ -613,8 +673,10 @@
* @return Existing map or {@code null} if not found.
*/
private PropertyMap checkHistory(final Property property) {
+
if (history != null) {
- PropertyMap historicMap = history.get(property);
+ SoftReference<PropertyMap> ref = history.get(property);
+ final PropertyMap historicMap = ref == null ? null : ref.get();
if (historicMap != null) {
if (Context.DEBUG) {
@@ -628,54 +690,6 @@
return null;
}
- /**
- * Calculate the hash code for the map.
- *
- * @return Computed hash code.
- */
- private int computeHashCode() {
- int hash = 0;
-
- for (final Property property : getProperties()) {
- hash = hash << 7 ^ hash >> 7;
- hash ^= property.hashCode();
- }
-
- return hash;
- }
-
- @Override
- public int hashCode() {
- if (hashCode == 0 && !properties.isEmpty()) {
- hashCode = computeHashCode();
- }
- return hashCode;
- }
-
- @Override
- public boolean equals(final Object other) {
- if (!(other instanceof PropertyMap)) {
- return false;
- }
-
- final PropertyMap otherMap = (PropertyMap)other;
-
- if (properties.size() != otherMap.properties.size()) {
- return false;
- }
-
- final Iterator<Property> iter = properties.values().iterator();
- final Iterator<Property> otherIter = otherMap.properties.values().iterator();
-
- while (iter.hasNext() && otherIter.hasNext()) {
- if (!iter.next().equals(otherIter.next())) {
- return false;
- }
- }
-
- return true;
- }
-
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
@@ -728,24 +742,6 @@
}
/**
- * Check whether a {@link PropertyListener} has been added to this map.
- *
- * @return {@code true} if {@link PropertyListener} exists
- */
- public boolean isListenerAdded() {
- return (flags & IS_LISTENER_ADDED) != 0;
- }
-
- /**
- * Check if this map shared or not.
- *
- * @return true if this map is shared.
- */
- public boolean isShared() {
- return (flags & IS_SHARED) != 0;
- }
-
- /**
* Test to see if {@link PropertyMap} is extensible.
*
* @return {@code true} if {@link PropertyMap} can be added to.
@@ -800,50 +796,29 @@
}
/**
- * Change the prototype of objects associated with this {@link PropertyMap}.
+ * Return a property map with the same layout that is associated with the new prototype object.
*
- * @param oldProto Current prototype object.
* @param newProto New prototype object to replace oldProto.
- *
* @return New {@link PropertyMap} with prototype changed.
*/
- PropertyMap changeProto(final ScriptObject oldProto, final ScriptObject newProto) {
- assert !isShared() : "proto associated with a shared PropertyMap";
+ public PropertyMap changeProto(final ScriptObject newProto) {
- if (oldProto == newProto) {
- return this;
- }
-
- final PropertyMap nextMap = checkProtoHistory(newProto);
+ final PropertyMap parentMap = newProto == null ? null : newProto.getMap();
+ final PropertyMap nextMap = checkProtoHistory(parentMap);
if (nextMap != null) {
return nextMap;
}
if (Context.DEBUG) {
- incrementSetProtoNewMapCount();
+ setProtoNewMapCount++;
}
final PropertyMap newMap = new PropertyMap(this);
- addToProtoHistory(newProto, newMap);
+ addToProtoHistory(parentMap, newMap);
return newMap;
}
- /**
- * Indicate that the map has listeners.
- */
- private void setIsListenerAdded() {
- flags |= IS_LISTENER_ADDED;
- }
-
- /**
- * Return only the flags that should be copied during cloning.
- *
- * @return Subset of flags that should be copied.
- */
- private int getClonedFlags() {
- return flags & CLONEABLE_FLAGS_MASK;
- }
/**
* {@link PropertyMap} iterator.
@@ -900,41 +875,12 @@
}
/*
- * PropertyListener implementation.
- */
-
- @Override
- public void propertyAdded(final ScriptObject object, final Property prop) {
- invalidateProtoGetSwitchPoint(prop);
- }
-
- @Override
- public void propertyDeleted(final ScriptObject object, final Property prop) {
- invalidateProtoGetSwitchPoint(prop);
- }
-
- @Override
- public void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
- invalidateProtoGetSwitchPoint(oldProp);
- }
-
- @Override
- public void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
- // We may walk and invalidate SwitchPoints for properties inherited
- // from 'object' or it's old proto chain. But, it may not be worth it.
- // For example, a new proto may have a user defined getter/setter for
- // a data property down the chain. So, invalidating all is better.
- invalidateAllProtoGetSwitchPoints();
- }
-
- /*
* Debugging and statistics.
*/
// counters updated only in debug mode
private static int count;
private static int clonedCount;
- private static int sharedCount;
private static int duplicatedCount;
private static int historyHit;
private static int protoInvalidations;
@@ -956,13 +902,6 @@
}
/**
- * @return The number of maps that are shared.
- */
- public static int getSharedCount() {
- return sharedCount;
- }
-
- /**
* @return The number of maps that are duplicated.
*/
public static int getDuplicatedCount() {
@@ -997,10 +936,4 @@
return setProtoNewMapCount;
}
- /**
- * Increment the prototype set count.
- */
- private static void incrementSetProtoNewMapCount() {
- setProtoNewMapCount++;
- }
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
index e5ca3c9..7e1a516 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
@@ -103,9 +103,7 @@
public RecompilableScriptFunctionData(final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, final PropertyMap allocatorMap) {
super(functionName(functionNode),
functionNode.getParameters().size(),
- functionNode.isStrict(),
- false,
- true);
+ getFlags(functionNode));
this.functionNode = functionNode;
this.source = functionNode.getSource();
@@ -129,10 +127,11 @@
final StringBuilder sb = new StringBuilder();
if (source != null) {
- sb.append(source.getName())
- .append(':')
- .append(functionNode.getLineNumber())
- .append(' ');
+ sb.append(source.getName());
+ if (functionNode != null) {
+ sb.append(':').append(functionNode.getLineNumber());
+ }
+ sb.append(' ');
}
return sb.toString() + super.toString();
@@ -159,11 +158,25 @@
return Token.toDesc(TokenType.FUNCTION, position, length);
}
+ private static int getFlags(final FunctionNode functionNode) {
+ int flags = IS_CONSTRUCTOR;
+ if (functionNode.isStrict()) {
+ flags |= IS_STRICT;
+ }
+ if (functionNode.needsCallee()) {
+ flags |= NEEDS_CALLEE;
+ }
+ if (functionNode.usesThis() || functionNode.hasEval()) {
+ flags |= USES_THIS;
+ }
+ return flags;
+ }
+
@Override
- ScriptObject allocate() {
+ ScriptObject allocate(final PropertyMap map) {
try {
ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try
- return allocator == null ? null : (ScriptObject)allocator.invokeExact(allocatorMap);
+ return allocator == null ? null : (ScriptObject)allocator.invokeExact(map);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
@@ -178,40 +191,46 @@
}
@Override
+ PropertyMap getAllocatorMap() {
+ return allocatorMap;
+ }
+
+
+ @Override
+ protected void ensureCompiled() {
+ if (functionNode != null && functionNode.isLazy()) {
+ Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
+ final Compiler compiler = new Compiler(installer);
+ functionNode = compiler.compile(functionNode);
+ assert !functionNode.isLazy();
+ compiler.install(functionNode);
+ flags = getFlags(functionNode);
+ }
+ }
+
+ @Override
protected synchronized void ensureCodeGenerated() {
- if (!code.isEmpty()) {
- return; // nothing to do, we have code, at least some.
- }
+ if (!code.isEmpty()) {
+ return; // nothing to do, we have code, at least some.
+ }
- if (functionNode.isLazy()) {
- Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
- final Compiler compiler = new Compiler(installer);
- functionNode = compiler.compile(functionNode);
- assert !functionNode.isLazy();
- compiler.install(functionNode);
+ ensureCompiled();
- /*
- * We don't need to update any flags - varArgs and needsCallee are instrincic
- * in the function world we need to get a destination node from the compile instead
- * and replace it with our function node. TODO
- */
- }
+ /*
+ * We can't get to this program point unless we have bytecode, either from
+ * eager compilation or from running a lazy compile on the lines above
+ */
- /*
- * We can't get to this program point unless we have bytecode, either from
- * eager compilation or from running a lazy compile on the lines above
- */
+ assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
- assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
+ // code exists - look it up and add it into the automatically sorted invoker list
+ addCode(functionNode);
- // code exists - look it up and add it into the automatically sorted invoker list
- addCode(functionNode);
-
- if (! functionNode.canSpecialize()) {
- // allow GC to claim IR stuff that is not needed anymore
- functionNode = null;
- installer = null;
- }
+ if (! functionNode.canSpecialize()) {
+ // allow GC to claim IR stuff that is not needed anymore
+ functionNode = null;
+ installer = null;
+ }
}
private MethodHandle addCode(final FunctionNode fn) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
index d0669d7..3d8b4ff 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
@@ -38,6 +38,7 @@
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
@@ -66,6 +67,8 @@
private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class);
+ private static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
+
/** method handle to scope getter for this ScriptFunction */
public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class);
@@ -80,6 +83,9 @@
private final ScriptFunctionData data;
+ /** The property map used for newly allocated object when function is used as constructor. */
+ protected PropertyMap allocatorMap;
+
/**
* Constructor
*
@@ -88,9 +94,7 @@
* @param map property map
* @param scope scope
* @param specs specialized version of this function - other method handles
- * @param strict is this a strict mode function?
- * @param builtin is this a built in function?
- * @param isConstructor is this a constructor?
+ * @param flags {@link ScriptFunctionData} flags
*/
protected ScriptFunction(
final String name,
@@ -98,11 +102,9 @@
final PropertyMap map,
final ScriptObject scope,
final MethodHandle[] specs,
- final boolean strict,
- final boolean builtin,
- final boolean isConstructor) {
+ final int flags) {
- this(new FinalScriptFunctionData(name, methodHandle, specs, strict, builtin, isConstructor), map, scope);
+ this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope);
}
/**
@@ -125,6 +127,7 @@
this.data = data;
this.scope = scope;
+ this.allocatorMap = data.getAllocatorMap();
}
@Override
@@ -229,16 +232,16 @@
}
assert !isBoundFunction(); // allocate never invoked on bound functions
- final ScriptObject object = data.allocate();
+ final ScriptObject object = data.allocate(allocatorMap);
if (object != null) {
Object prototype = getPrototype();
if (prototype instanceof ScriptObject) {
- object.setProto((ScriptObject)prototype);
+ object.setInitialProto((ScriptObject)prototype);
}
if (object.getProto() == null) {
- object.setProto(getObjectPrototype());
+ object.setInitialProto(getObjectPrototype());
}
}
@@ -473,7 +476,14 @@
if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) {
return obj;
}
- return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(obj);
+ return Context.getGlobal().wrapAsObject(obj);
+ }
+
+
+ @SuppressWarnings("unused")
+ private static Object globalFilter(final Object object) {
+ // replace whatever we get with the current global object
+ return Context.getGlobal();
}
/**
@@ -491,11 +501,11 @@
@Override
protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType type = desc.getMethodType();
+ final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
if (request.isCallSiteUnstable()) {
- // (this, callee, args...) => (this, callee, args[])
- final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class,
- type.parameterCount() - 2);
+ // (callee, this, args...) => (callee, this, args[])
+ final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2);
// If call site is statically typed to take a ScriptFunction, we don't need a guard, otherwise we need a
// generic "is this a ScriptFunction?" guard.
@@ -506,17 +516,12 @@
MethodHandle boundHandle;
MethodHandle guard = null;
- final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
-
if (data.needsCallee()) {
final MethodHandle callHandle = getBestInvoker(type, request.getArguments());
- if (scopeCall) {
+ if (scopeCall && needsWrappedThis()) {
// Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
- // (callee, this, args...) => (callee, args...)
- boundHandle = MH.insertArguments(callHandle, 1, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
- // (callee, args...) => (callee, [this], args...)
- boundHandle = MH.dropArguments(boundHandle, 1, Object.class);
-
+ // (callee, this, args...) => (callee, [this], args...)
+ boundHandle = MH.filterArguments(callHandle, 1, GLOBALFILTER);
} else {
// It's already (callee, this, args...), just what we need
boundHandle = callHandle;
@@ -527,12 +532,12 @@
// NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
// current lookup as its "this" so it can do security-sensitive creation of adapter classes.
boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class);
- } else if (scopeCall) {
+ } else if (scopeCall && needsWrappedThis()) {
// Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
- // (this, args...) => (args...)
- boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
- // (args...) => ([callee], [this], args...)
- boundHandle = MH.dropArguments(boundHandle, 0, Object.class, Object.class);
+ // (this, args...) => ([this], args...)
+ boundHandle = MH.filterArguments(callHandle, 0, GLOBALFILTER);
+ // ([this], args...) => ([callee], [this], args...)
+ boundHandle = MH.dropArguments(boundHandle, 0, Object.class);
} else {
// (this, args...) => ([callee], this, args...)
boundHandle = MH.dropArguments(callHandle, 0, Object.class);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
index 4dbbfba..aee367d 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
@@ -32,6 +32,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
/**
@@ -47,33 +48,44 @@
/** All versions of this function that have been generated to code */
protected final CompiledFunctions code;
+ /** Function flags */
+ protected int flags;
+
private int arity;
- private final boolean isStrict;
-
- private final boolean isBuiltin;
-
- private final boolean isConstructor;
-
private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class);
private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class);
+ /** Is this a strict mode function? */
+ public static final int IS_STRICT = 1 << 0;
+ /** Is this a built-in function? */
+ public static final int IS_BUILTIN = 1 << 1;
+ /** Is this a constructor function? */
+ public static final int IS_CONSTRUCTOR = 1 << 2;
+ /** Does this function expect a callee argument? */
+ public static final int NEEDS_CALLEE = 1 << 3;
+ /** Does this function make use of the this-object argument? */
+ public static final int USES_THIS = 1 << 4;
+
+ /** Flag for strict or built-in functions */
+ public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
+ /** Flag for built-in constructors */
+ public static final int IS_BUILTIN_CONSTRUCTOR = IS_BUILTIN | IS_CONSTRUCTOR;
+ /** Flag for strict constructors */
+ public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR;
+
/**
* Constructor
*
* @param name script function name
* @param arity arity
- * @param isStrict is the function strict
- * @param isBuiltin is the function built in
- * @param isConstructor is the function a constructor
+ * @param flags the function flags
*/
- ScriptFunctionData(final String name, final int arity, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
- this.name = name;
- this.arity = arity;
- this.code = new CompiledFunctions();
- this.isStrict = isStrict;
- this.isBuiltin = isBuiltin;
- this.isConstructor = isConstructor;
+ ScriptFunctionData(final String name, final int arity, final int flags) {
+ this.name = name;
+ this.arity = arity;
+ this.code = new CompiledFunctions();
+ this.flags = flags;
}
final int getArity() {
@@ -105,21 +117,21 @@
* @return true if strict, false otherwise
*/
public boolean isStrict() {
- return isStrict;
+ return (flags & IS_STRICT) != 0;
}
boolean isBuiltin() {
- return isBuiltin;
+ return (flags & IS_BUILTIN) != 0;
}
boolean isConstructor() {
- return isConstructor;
+ return (flags & IS_CONSTRUCTOR) != 0;
}
boolean needsCallee() {
- // we don't know if we need a callee or not unless we are generated
- ensureCodeGenerated();
- return code.needsCallee();
+ // we don't know if we need a callee or not unless code has been compiled
+ ensureCompiled();
+ return (flags & NEEDS_CALLEE) != 0;
}
/**
@@ -128,7 +140,7 @@
* @return true if this argument must be an object
*/
boolean needsWrappedThis() {
- return !isStrict && !isBuiltin;
+ return (flags & USES_THIS) != 0 && (flags & IS_STRICT_OR_BUILTIN) == 0;
}
String toSource() {
@@ -202,6 +214,15 @@
}
/**
+ * If we can have lazy code generation, this is a hook to ensure that the code has been compiled.
+ * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance;
+ * use {@link #ensureCodeGenerated()} to install the actual method handles.
+ */
+ protected void ensureCompiled() {
+ //empty
+ }
+
+ /**
* Return a generic Object/Object invoker for this method. It will ensure code
* is generated, get the most generic of all versions of this function and adapt it
* to Objects.
@@ -229,9 +250,20 @@
/**
* Allocates an object using this function's allocator.
+ *
+ * @param map the property map for the allocated object.
* @return the object allocated using this function's allocator, or null if the function doesn't have an allocator.
*/
- ScriptObject allocate() {
+ ScriptObject allocate(final PropertyMap map) {
+ return null;
+ }
+
+ /**
+ * Get the property map to use for objects allocated by this function.
+ *
+ * @return the property map for allocated objects.
+ */
+ PropertyMap getAllocatorMap() {
return null;
}
@@ -248,6 +280,8 @@
final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args;
final int length = args == null ? 0 : args.length;
+ // Clear the callee and this flags
+ final int boundFlags = flags & ~NEEDS_CALLEE & ~USES_THIS;
CompiledFunctions boundList = new CompiledFunctions();
if (code.size() == 1) {
@@ -262,8 +296,7 @@
boundList.add(bind(inv, fn, self, allArgs));
}
- ScriptFunctionData boundData = new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, isStrict(), isBuiltin(), isConstructor());
- return boundData;
+ return new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, boundFlags);
}
/**
@@ -340,11 +373,11 @@
private Object convertThisObject(final Object thiz) {
if (!(thiz instanceof ScriptObject) && needsWrappedThis()) {
if (JSType.nullOrUndefined(thiz)) {
- return Context.getGlobalTrusted();
+ return Context.getGlobal();
}
if (isPrimitiveThis(thiz)) {
- return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(thiz);
+ return Context.getGlobal().wrapAsObject(thiz);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java
index 78185b1..52c98d4 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java
@@ -70,9 +70,8 @@
* @return Installed class.
*/
synchronized Class<?> installClass(final String name, final byte[] data, final CodeSource cs) {
- if (cs == null) {
- return defineClass(name, data, 0, data.length, new ProtectionDomain(null, getPermissions(null)));
- }
+ // null check
+ cs.getClass();
return defineClass(name, data, 0, data.length, cs);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
index 02160d6..1519024 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
@@ -43,6 +43,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
@@ -65,6 +66,7 @@
import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
import jdk.nashorn.internal.objects.DataPropertyDescriptor;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -88,7 +90,7 @@
* </ul>
*/
-public abstract class ScriptObject extends PropertyListenerManager implements PropertyAccess {
+public abstract class ScriptObject implements PropertyAccess {
/** __proto__ special property name */
public static final String PROTO_PROPERTY_NAME = "__proto__";
@@ -107,9 +109,6 @@
/** Per ScriptObject flag - is this an arguments object? */
public static final int IS_ARGUMENTS = 0b0000_0100;
- /** Is this a prototype PropertyMap? */
- public static final int IS_PROTOTYPE = 0b0000_1000;
-
/** Is length property not-writable? */
public static final int IS_LENGTH_NOT_WRITABLE = 0b0001_0000;
@@ -133,7 +132,8 @@
static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class);
static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class);
- static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class);
+ static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class, boolean.class);
+ static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
@@ -143,6 +143,8 @@
private static final MethodHandle TRUNCATINGFILTER = findOwnMH("truncatingFilter", Object[].class, int.class, Object[].class);
private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
+ private static final ArrayList<MethodHandle> protoFilters = new ArrayList<>();
+
/** Method handle for getting a function argument at a given index. Used from MapCreator */
public static final Call GET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArgument", Object.class, int.class);
@@ -153,7 +155,7 @@
public static final Call GET_PROTO = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
/** Method handle for setting the proto of a ScriptObject */
- public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setProto", void.class, ScriptObject.class);
+ public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class);
/** Method handle for setting the proto of a ScriptObject after checking argument */
public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class);
@@ -199,10 +201,6 @@
this.arrayData = ArrayData.EMPTY_ARRAY;
this.setMap(map == null ? PropertyMap.newMap() : map);
this.proto = proto;
-
- if (proto != null) {
- proto.setIsPrototype();
- }
}
/**
@@ -229,8 +227,9 @@
final Property oldProp = newMap.findProperty(key);
if (oldProp == null) {
if (property instanceof UserAccessorProperty) {
+ // Note: we copy accessor functions to this object which is semantically different from binding.
final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
- newMap = newMap.addProperty(prop);
+ newMap = newMap.addPropertyNoHistory(prop);
} else {
newMap = newMap.addPropertyBind((AccessorProperty)property, source);
}
@@ -326,18 +325,18 @@
* @return property descriptor
*/
public final PropertyDescriptor toPropertyDescriptor() {
- final GlobalObject global = (GlobalObject) Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
final PropertyDescriptor desc;
if (isDataDescriptor()) {
if (has(SET) || has(GET)) {
- throw typeError((ScriptObject)global, "inconsistent.property.descriptor");
+ throw typeError(global, "inconsistent.property.descriptor");
}
desc = global.newDataDescriptor(UNDEFINED, false, false, false);
} else if (isAccessorDescriptor()) {
if (has(VALUE) || has(WRITABLE)) {
- throw typeError((ScriptObject)global, "inconsistent.property.descriptor");
+ throw typeError(global, "inconsistent.property.descriptor");
}
desc = global.newAccessorDescriptor(UNDEFINED, UNDEFINED, false, false);
@@ -356,7 +355,7 @@
*
* @return property descriptor
*/
- public static PropertyDescriptor toPropertyDescriptor(final ScriptObject global, final Object obj) {
+ public static PropertyDescriptor toPropertyDescriptor(final Global global, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).toPropertyDescriptor();
}
@@ -375,7 +374,7 @@
public Object getOwnPropertyDescriptor(final String key) {
final Property property = getMap().findProperty(key);
- final GlobalObject global = (GlobalObject)Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
if (property != null) {
final ScriptFunction get = property.getGetterFunction(this);
@@ -440,7 +439,7 @@
* @return true if property was successfully defined
*/
public boolean defineOwnProperty(final String key, final Object propertyDesc, final boolean reject) {
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
final PropertyDescriptor desc = toPropertyDescriptor(global, propertyDesc);
final Object current = getOwnPropertyDescriptor(key);
final String name = JSType.toString(key);
@@ -467,7 +466,7 @@
return true;
}
- if (currentDesc.equals(newDesc)) {
+ if (newDesc.hasAndEquals(currentDesc)) {
// every descriptor field of the new is same as the current
return true;
}
@@ -594,23 +593,16 @@
}
/**
- * Spec. mentions use of [[DefineOwnProperty]] for indexed properties in
- * certain places (eg. Array.prototype.map, filter). We can not use ScriptObject.set
- * method in such cases. This is because set method uses inherited setters (if any)
- * from any object in proto chain such as Array.prototype, Object.prototype.
- * This method directly sets a particular element value in the current object.
+ * Almost like defineOwnProperty(int,Object) for arrays this one does
+ * not add 'gap' elements (like the array one does).
*
* @param index key for property
* @param value value to define
*/
- public final void defineOwnProperty(final int index, final Object value) {
+ public void defineOwnProperty(final int index, final Object value) {
assert isValidArrayIndex(index) : "invalid array index";
final long longIndex = ArrayIndex.toLongIndex(index);
- if (longIndex >= getArray().length()) {
- // make array big enough to hold..
- setArray(getArray().ensure(longIndex));
- }
- setArray(getArray().set(index, value, false));
+ setValueAtArrayIndex(longIndex, index, value, false);
}
private void checkIntegerKey(final String key) {
@@ -638,7 +630,7 @@
final int propFlags = Property.toFlags(pdesc);
if (pdesc.type() == PropertyDescriptor.GENERIC) {
- final GlobalObject global = (GlobalObject) Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
final PropertyDescriptor dDesc = global.newDataDescriptor(UNDEFINED, false, false, false);
dDesc.fillFrom((ScriptObject)pdesc);
@@ -873,8 +865,6 @@
newProperty = newUserAccessors(oldProperty.getKey(), propertyFlags, getter, setter);
}
- notifyPropertyModified(this, oldProperty, newProperty);
-
return modifyOwnProperty(oldProperty, newProperty);
}
@@ -981,17 +971,6 @@
}
/**
- * Get the object value of a property
- *
- * @param find {@link FindProperty} lookup result
- *
- * @return the value of the property
- */
- protected static Object getObjectValue(final FindProperty find) {
- return find.getObjectValue();
- }
-
- /**
* Return methodHandle of value function for call.
*
* @param find data from find property.
@@ -1001,7 +980,7 @@
* @return value of property as a MethodHandle or null.
*/
protected MethodHandle getCallMethodHandle(final FindProperty find, final MethodType type, final String bindName) {
- return getCallMethodHandle(getObjectValue(find), type, bindName);
+ return getCallMethodHandle(find.getObjectValue(), type, bindName);
}
/**
@@ -1025,7 +1004,7 @@
* @return Value of property.
*/
public final Object getWithProperty(final Property property) {
- return getObjectValue(new FindProperty(this, this, property));
+ return new FindProperty(this, this, property).getObjectValue();
}
/**
@@ -1118,29 +1097,33 @@
*/
public synchronized final void setProto(final ScriptObject newProto) {
final ScriptObject oldProto = proto;
- map = map.changeProto(oldProto, newProto);
- if (newProto != null) {
- newProto.setIsPrototype();
- }
+ if (oldProto != newProto) {
+ proto = newProto;
- proto = newProto;
-
- if (isPrototype()) {
- // tell listeners that my __proto__ has been changed
- notifyProtoChanged(this, oldProto, newProto);
-
- if (oldProto != null) {
- oldProto.removePropertyListener(this);
+ // Let current listeners know that the protototype has changed and set our map
+ final PropertyListeners listeners = getMap().getListeners();
+ if (listeners != null) {
+ listeners.protoChanged();
}
-
- if (newProto != null) {
- newProto.addPropertyListener(this);
- }
+ // Replace our current allocator map with one that is associated with the new prototype.
+ setMap(getMap().changeProto(newProto));
}
}
/**
+ * Set the initial __proto__ of this object. This should be used instead of
+ * {@link #setProto} if it is known that the current property map will not be
+ * used on a new object with any other parent property map, so we can pass over
+ * property map invalidation/evolution.
+ *
+ * @param initialProto the initial __proto__ to set.
+ */
+ public void setInitialProto(final ScriptObject initialProto) {
+ this.proto = initialProto;
+ }
+
+ /**
* Set the __proto__ of an object with checks.
* @param newProto Prototype to set.
*/
@@ -1160,7 +1143,7 @@
}
setProto((ScriptObject)newProto);
} else {
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
final Object newProtoObject = JSType.toScriptObject(global, newProto);
if (newProtoObject instanceof ScriptObject) {
@@ -1250,11 +1233,11 @@
* @return the default value
*/
public Object getDefaultValue(final Class<?> typeHint) {
- // We delegate to GlobalObject, as the implementation uses dynamic call sites to invoke object's "toString" and
+ // We delegate to Global, as the implementation uses dynamic call sites to invoke object's "toString" and
// "valueOf" methods, and in order to avoid those call sites from becoming megamorphic when multiple contexts
// are being executed in a long-running program, we move the code and their associated dynamic call sites
// (Global.TO_STRING and Global.VALUE_OF) into per-context code.
- return ((GlobalObject)Context.getGlobalTrusted()).getDefaultValue(this, typeHint);
+ return Context.getGlobal().getDefaultValue(this, typeHint);
}
/**
@@ -1330,25 +1313,6 @@
}
/**
- * Check if this object is a prototype
- *
- * @return {@code true} if is prototype
- */
- public final boolean isPrototype() {
- return (flags & IS_PROTOTYPE) != 0;
- }
-
- /**
- * Flag this object as having a prototype.
- */
- public final void setIsPrototype() {
- if (proto != null && !isPrototype()) {
- proto.addPropertyListener(this);
- }
- flags |= IS_PROTOTYPE;
- }
-
- /**
* Check if this object has non-writable length property
*
* @return {@code true} if 'length' property is non-writable
@@ -1712,6 +1676,44 @@
}
/**
+ * Test whether this object contains in its prototype chain or is itself a with-object.
+ * @return true if a with-object was found
+ */
+ final boolean hasWithScope() {
+ if (isScope()) {
+ for (ScriptObject obj = this; obj != null; obj = obj.getProto()) {
+ if (obj instanceof WithObject) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Add a filter to the first argument of {@code methodHandle} that calls its {@link #getProto()} method
+ * {@code depth} times.
+ * @param methodHandle a method handle
+ * @param depth distance to target prototype
+ * @return the filtered method handle
+ */
+ static MethodHandle addProtoFilter(final MethodHandle methodHandle, final int depth) {
+ if (depth == 0) {
+ return methodHandle;
+ }
+ final int listIndex = depth - 1; // We don't need 0-deep walker
+ MethodHandle filter = listIndex < protoFilters.size() ? protoFilters.get(listIndex) : null;
+
+ if(filter == null) {
+ filter = addProtoFilter(GETPROTO, depth - 1);
+ protoFilters.add(null);
+ protoFilters.set(listIndex, filter);
+ }
+
+ return MH.filterArguments(methodHandle, 0, filter.asType(filter.type().changeReturnType(methodHandle.type().parameterType(0))));
+ }
+
+ /**
* Find the appropriate GET method for an invoke dynamic call.
*
* @param desc the call site descriptor
@@ -1722,8 +1724,8 @@
*/
protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- if (request.isCallSiteUnstable()) {
- return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator));
+ if (request.isCallSiteUnstable() || hasWithScope()) {
+ return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator), isScope() && NashornCallSiteDescriptor.isScope(desc));
}
final FindProperty find = findProperty(name, true);
@@ -1748,40 +1750,43 @@
final Property property = find.getProperty();
methodHandle = find.getGetter(returnType);
- // getMap() is fine as we have the prototype switchpoint depending on where the property was found
- final MethodHandle guard = NashornGuards.getMapGuard(getMap());
+ // Get the appropriate guard for this callsite and property.
+ final MethodHandle guard = NashornGuards.getGuard(this, property, desc);
+ final ScriptObject owner = find.getOwner();
if (methodHandle != null) {
assert methodHandle.type().returnType().equals(returnType);
if (find.isSelf()) {
- return new GuardedInvocation(methodHandle, ObjectClassGenerator.OBJECT_FIELDS_ONLY &&
- NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType() ? null : guard);
+ return new GuardedInvocation(methodHandle, guard);
}
- final ScriptObject prototype = find.getOwner();
-
- if (!property.hasGetterFunction(prototype)) {
- methodHandle = bindTo(methodHandle, prototype);
+ if (!property.hasGetterFunction(owner)) {
+ // Add a filter that replaces the self object with the prototype owning the property.
+ methodHandle = addProtoFilter(methodHandle, find.getProtoChainLength());
}
- return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(proto, name), guard);
+ return new GuardedInvocation(methodHandle, guard == null ? null : getProtoSwitchPoint(name, owner), guard);
}
assert !NashornCallSiteDescriptor.isFastScope(desc);
- return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(proto, name), guard);
+ return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
}
- private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
- final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
+ private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name,
+ final boolean isMethod, final boolean isScope) {
+ final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, isScope);
final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
return new GuardedInvocation(invoker, guard);
}
@SuppressWarnings("unused")
- private Object megamorphicGet(final String key, final boolean isMethod) {
+ private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
final FindProperty find = findProperty(key, true);
if (find != null) {
- return getObjectValue(find);
+ return find.getObjectValue();
+ }
+ if (isScope) {
+ throw referenceError("not.defined", key);
}
return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
@@ -1824,6 +1829,28 @@
}
/**
+ * Get a switch point for a property with the given {@code name} that will be invalidated when
+ * the property definition is changed in this object's prototype chain. Returns {@code null} if
+ * the property is defined in this object itself.
+ *
+ * @param name the property name
+ * @param owner the property owner, null if property is not defined
+ * @return a SwitchPoint or null
+ */
+ public final SwitchPoint getProtoSwitchPoint(final String name, final ScriptObject owner) {
+ if (owner == this || getProto() == null) {
+ return null;
+ }
+
+ for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
+ ScriptObject parent = obj.getProto();
+ parent.getMap().addListener(name, obj.getMap());
+ }
+
+ return getMap().getSwitchPoint(name);
+ }
+
+ /**
* Find the appropriate SET method for an invoke dynamic call.
*
* @param desc the call site descriptor
@@ -1833,7 +1860,7 @@
*/
protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- if (request.isCallSiteUnstable()) {
+ if (request.isCallSiteUnstable() || hasWithScope()) {
return findMegaMorphicSetMethod(desc, name);
}
@@ -1879,8 +1906,7 @@
throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString((this)));
}
assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
- final PropertyMap myMap = getMap();
- return new GuardedInvocation(Lookup.EMPTY_SETTER, myMap.getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(myMap));
+ return new GuardedInvocation(Lookup.EMPTY_SETTER, getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
}
@SuppressWarnings("unused")
@@ -1888,7 +1914,9 @@
final ScriptObject obj = (ScriptObject)self;
final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
if (!obj.isExtensible()) {
- throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
+ if (isStrict) {
+ throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
+ }
} else if (obj.compareAndSetMap(oldMap, newMap)) {
setter.invokeExact(self, value);
} else {
@@ -1953,6 +1981,15 @@
}
}
+ @SuppressWarnings("unused")
+ private static Object globalFilter(final Object object) {
+ ScriptObject sobj = (ScriptObject) object;
+ while (sobj != null && !(sobj instanceof Global)) {
+ sobj = sobj.getProto();
+ }
+ return sobj;
+ }
+
private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc));
@@ -1998,7 +2035,7 @@
return noSuchProperty(desc, request);
}
- final Object value = getObjectValue(find);
+ final Object value = find.getObjectValue();
if (! (value instanceof ScriptFunction)) {
return createEmptyGetter(desc, name);
}
@@ -2024,7 +2061,7 @@
final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
if (find != null) {
- final Object value = getObjectValue(find);
+ final Object value = find.getObjectValue();
ScriptFunction func = null;
MethodHandle methodHandle = null;
@@ -2038,7 +2075,7 @@
methodHandle = bindTo(methodHandle, UNDEFINED);
}
return new GuardedInvocation(methodHandle,
- find.isInherited()? getMap().getProtoGetSwitchPoint(proto, NO_SUCH_PROPERTY_NAME) : null,
+ getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
getKnownFunctionPropertyGuard(getMap(), find.getGetter(Object.class), find.getOwner(), func));
}
}
@@ -2049,16 +2086,17 @@
return createEmptyGetter(desc, name);
}
+
/**
* Invoke fall back if a property is not found.
* @param name Name of property.
* @return Result from call.
*/
- private Object invokeNoSuchProperty(final String name) {
+ protected Object invokeNoSuchProperty(final String name) {
final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
if (find != null) {
- final Object func = getObjectValue(find);
+ final Object func = find.getObjectValue();
if (func instanceof ScriptFunction) {
return ScriptRuntime.apply((ScriptFunction)func, this, name);
@@ -2080,7 +2118,7 @@
return invokeNoSuchProperty(name);
}
- final Object value = getObjectValue(find);
+ final Object value = find.getObjectValue();
if (! (value instanceof ScriptFunction)) {
return UNDEFINED;
}
@@ -2089,7 +2127,8 @@
}
private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
- return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(getMap()));
+ return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
+ getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
}
private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
@@ -2170,12 +2209,10 @@
if (fieldCount < fieldMaximum) {
property = new AccessorProperty(key, propertyFlags & ~Property.IS_SPILL, getClass(), fieldCount);
- notifyPropertyAdded(this, property);
property = addOwnProperty(property);
} else {
int i = getMap().getSpillLength();
property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i);
- notifyPropertyAdded(this, property);
property = addOwnProperty(property);
i = property.getSlot();
@@ -2621,7 +2658,7 @@
final FindProperty find = object.findProperty(key, false, false, this);
if (find != null) {
- return getObjectValue(find);
+ return find.getObjectValue();
}
}
@@ -2639,7 +2676,7 @@
final FindProperty find = findProperty(key, true);
if (find != null) {
- return getObjectValue(find);
+ return find.getObjectValue();
}
}
@@ -2703,9 +2740,7 @@
* @param strict are we in strict mode
*/
private void doesNotHave(final int index, final Object value, final boolean strict) {
- final long oldLength = getArray().length();
final long longIndex = ArrayIndex.toLongIndex(index);
-
if (getMap().containsArrayKeys()) {
final String key = JSType.toString(longIndex);
final FindProperty find = findProperty(key, true);
@@ -2716,6 +2751,18 @@
}
}
+ setValueAtArrayIndex(longIndex, index, value, strict);
+ }
+
+ /**
+ * Handle when an array doesn't have a slot - possibly grow and/or convert array.
+ *
+ * @param index key as index
+ * @param value element value
+ * @param strict are we in strict mode
+ */
+ private void setValueAtArrayIndex(final long longIndex, final int index, final Object value, final boolean strict) {
+ final long oldLength = getArray().length();
if (longIndex >= oldLength) {
if (!isExtensible()) {
if (strict) {
@@ -2759,7 +2806,8 @@
public final void setObject(final FindProperty find, final boolean strict, final String key, final Object value) {
FindProperty f = find;
- if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
+ if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty) && !isScope()) {
+ // Setting a property should not modify the property in prototype unless this is a scope object.
f = null;
}
@@ -2779,7 +2827,15 @@
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
}
} else {
- spill(key, value);
+ ScriptObject sobj = this;
+ // undefined scope properties are set in the global object.
+ if (isScope()) {
+ while (sobj != null && !(sobj instanceof Global)) {
+ sobj = sobj.getProto();
+ }
+ assert sobj != null : "no parent global object in scope";
+ }
+ sobj.spill(key, value);
}
}
@@ -3228,7 +3284,6 @@
}
final Property prop = find.getProperty();
- notifyPropertyDeleted(this, prop);
deleteOwnProperty(prop);
return true;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
index d970567..6df047d 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
@@ -474,7 +474,7 @@
* @return {@link WithObject} that is the new scope
*/
public static ScriptObject openWith(final ScriptObject scope, final Object expression) {
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
if (expression == UNDEFINED) {
throw typeError(global, "cant.apply.with.to.undefined");
} else if (expression == null) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
index 777254d..edee374 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
@@ -31,7 +31,6 @@
import java.lang.invoke.MethodHandle;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
@@ -80,7 +79,7 @@
}
/**
- * This class encapsulates the results of looking up a setter method; it's basically a triple of a method hanle,
+ * This class encapsulates the results of looking up a setter method; it's basically a triple of a method handle,
* a Property object, and flags for invocation.
*
*/
@@ -104,21 +103,9 @@
* @return the composed guarded invocation that represents the dynamic setter method for the property.
*/
GuardedInvocation createGuardedInvocation() {
- return new GuardedInvocation(methodHandle, getGuard());
+ return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc));
}
- private MethodHandle getGuard() {
- return needsNoGuard() ? null : NashornGuards.getMapGuard(getMap());
- }
-
- private boolean needsNoGuard() {
- return NashornCallSiteDescriptor.isFastScope(desc) &&
- (ObjectClassGenerator.OBJECT_FIELDS_ONLY || isPropertyTypeStable());
- }
-
- private boolean isPropertyTypeStable() {
- return property == null || !property.canChangeType();
- }
}
private SetMethod createSetMethod() {
@@ -151,10 +138,9 @@
assert methodHandle != null;
assert property != null;
- final ScriptObject prototype = find.getOwner();
final MethodHandle boundHandle;
- if (!property.hasSetterFunction(prototype) && find.isInherited()) {
- boundHandle = ScriptObject.bindTo(methodHandle, prototype);
+ if (!property.hasSetterFunction(find.getOwner()) && find.isInherited()) {
+ boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength());
} else {
boundHandle = methodHandle;
}
@@ -162,13 +148,16 @@
}
private SetMethod createGlobalPropertySetter() {
- final ScriptObject global = Context.getGlobalTrusted();
- return new SetMethod(ScriptObject.bindTo(global.addSpill(getName()), global), null);
+ final ScriptObject global = Context.getGlobal();
+ return new SetMethod(MH.filterArguments(global.addSpill(getName()), 0, ScriptObject.GLOBALFILTER), null);
}
private SetMethod createNewPropertySetter() {
final SetMethod sm = map.getFieldCount() < map.getFieldMaximum() ? createNewFieldSetter() : createNewSpillPropertySetter();
- sobj.notifyPropertyAdded(sobj, sm.property);
+ final PropertyListeners listeners = map.getListeners();
+ if (listeners != null) {
+ listeners.propertyAdded(sm.property);
+ }
return sm;
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
index 931d712..a69de45 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
@@ -34,6 +34,7 @@
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import jdk.nashorn.internal.objects.Global;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@@ -73,7 +74,7 @@
private static MethodHandle getINVOKE_UA_GETTER() {
- return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(INVOKE_UA_GETTER,
+ return Context.getGlobal().getDynamicInvoker(INVOKE_UA_GETTER,
new Callable<MethodHandle>() {
@Override
public MethodHandle call() {
@@ -86,7 +87,7 @@
/** Dynamic invoker for setter */
private static Object INVOKE_UA_SETTER = new Object();
private static MethodHandle getINVOKE_UA_SETTER() {
- return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(INVOKE_UA_SETTER,
+ return Context.getGlobal().getDynamicInvoker(INVOKE_UA_SETTER,
new Callable<MethodHandle>() {
@Override
public MethodHandle call() {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java
index 6e03dc6..dc48d72 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java
@@ -36,6 +36,7 @@
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+import jdk.nashorn.internal.runtime.linker.NashornGuards;
/**
* This class supports the handling of scope in a with body.
@@ -87,6 +88,11 @@
@Override
public GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request) {
+ if (request.isCallSiteUnstable()) {
+ // Fall back to megamorphic invocation which performs a complete lookup each time without further relinking.
+ return super.lookup(desc, request);
+ }
+
// With scopes can never be observed outside of Nashorn code, so all call sites that can address it will of
// necessity have a Nashorn descriptor - it is safe to cast.
final NashornCallSiteDescriptor ndesc = (NashornCallSiteDescriptor)desc;
@@ -123,7 +129,7 @@
}
if (find != null) {
- return fixScopeCallSite(scope.lookup(desc, request), name);
+ return fixScopeCallSite(scope.lookup(desc, request), name, find.getOwner());
}
// the property is not found - now check for
@@ -175,7 +181,7 @@
link = scope.lookup(desc, request);
if (link != null) {
- return fixScopeCallSite(link, name);
+ return fixScopeCallSite(link, name, null);
}
return null;
@@ -252,13 +258,10 @@
filterGuard(link, WITHEXPRESSIONFILTER));
}
- private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name) {
+ private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name, final ScriptObject owner) {
final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER);
return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER),
- MH.guardWithTest(
- expressionGuard(name),
- filterGuard(newLink, WITHSCOPEFILTER),
- MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class)));
+ NashornGuards.combineGuards(expressionGuard(name, owner), filterGuard(newLink, WITHSCOPEFILTER)));
}
private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) {
@@ -267,7 +270,7 @@
}
private static MethodHandle filter(final MethodHandle mh, final MethodHandle filter) {
- return MH.filterArguments(mh, 0, filter);
+ return MH.filterArguments(mh, 0, filter.asType(filter.type().changeReturnType(mh.type().parameterType(0))));
}
/**
@@ -288,9 +291,9 @@
return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]);
}
- private MethodHandle expressionGuard(final String name) {
+ private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
final PropertyMap map = expression.getMap();
- final SwitchPoint sp = map.getProtoGetSwitchPoint(expression.getProto(), name);
+ final SwitchPoint sp = expression.getProtoSwitchPoint(name, owner);
return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp);
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
index 5c0c047..58f3296 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
@@ -26,7 +26,8 @@
package jdk.nashorn.internal.runtime.arrays;
import java.lang.invoke.MethodHandle;
-import jdk.nashorn.internal.runtime.GlobalObject;
+import java.nio.ByteBuffer;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
@@ -144,6 +145,16 @@
}
/**
+ * Allocate an ArrayData wrapping a given nio ByteBuffer
+ *
+ * @param buf the nio ByteBuffer to wrap
+ * @return the ArrayData
+ */
+ public static ArrayData allocate(final ByteBuffer buf) {
+ return new ByteBufferArrayData((ByteBuffer)buf);
+ }
+
+ /**
* Apply a freeze filter to an ArrayData.
*
* @param underlying the underlying ArrayData to wrap in the freeze filter
@@ -388,7 +399,7 @@
*
* @return property descriptor for element
*/
- public PropertyDescriptor getDescriptor(final GlobalObject global, final int index) {
+ public PropertyDescriptor getDescriptor(final Global global, final int index) {
return global.newDataDescriptor(getObject(index), true, true, true);
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
new file mode 100644
index 0000000..33c8679
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2014, 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 jdk.nashorn.internal.runtime.arrays;
+
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
+import java.nio.ByteBuffer;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.PropertyDescriptor;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Implementation of {@link ArrayData} that wraps a nio ByteBuffer
+ */
+final class ByteBufferArrayData extends ArrayData {
+ private final ByteBuffer buf;
+
+ ByteBufferArrayData(final int length) {
+ super(length);
+ this.buf = ByteBuffer.allocateDirect(length);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param buf ByteBuffer to create array data with.
+ */
+ ByteBufferArrayData(final ByteBuffer buf) {
+ super(buf.capacity());
+ this.buf = buf;
+ }
+
+ /**
+ * Returns property descriptor for element at a given index
+ *
+ * @param global the global object
+ * @param index the index
+ *
+ * @return property descriptor for element
+ */
+ @Override
+ public PropertyDescriptor getDescriptor(final Global global, final int index) {
+ // make the index properties not configurable
+ return global.newDataDescriptor(getObject(index), false, true, true);
+ }
+
+ @Override
+ public ArrayData copy() {
+ throw unsupported("copy");
+ }
+
+ @Override
+ public Object[] asObjectArray() {
+ throw unsupported("asObjectArray");
+ }
+
+ @Override
+ public void setLength(final long length) {
+ throw new UnsupportedOperationException("setLength");
+ }
+
+ @Override
+ public void shiftLeft(int by) {
+ throw unsupported("shiftLeft");
+ }
+
+ @Override
+ public ArrayData shiftRight(int by) {
+ throw unsupported("shiftRight");
+ }
+
+ @Override
+ public ArrayData ensure(long safeIndex) {
+ if (safeIndex < buf.capacity()) {
+ return this;
+ }
+
+ throw unsupported("ensure");
+ }
+
+ @Override
+ public ArrayData shrink(long newLength) {
+ throw unsupported("shrink");
+ }
+
+ @Override
+ public ArrayData set(int index, Object value, boolean strict) {
+ if (value instanceof Number) {
+ buf.put(index, ((Number)value).byteValue());
+ return this;
+ }
+
+ throw typeError("not.a.number", ScriptRuntime.safeToString(value));
+ }
+
+ @Override
+ public ArrayData set(int index, int value, boolean strict) {
+ buf.put(index, (byte)value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(int index, long value, boolean strict) {
+ buf.put(index, (byte)value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(int index, double value, boolean strict) {
+ buf.put(index, (byte)value);
+ return this;
+ }
+
+ @Override
+ public int getInt(int index) {
+ return 0x0ff & buf.get(index);
+ }
+
+ @Override
+ public long getLong(int index) {
+ return 0x0ff & buf.get(index);
+ }
+
+ @Override
+ public double getDouble(int index) {
+ return 0x0ff & buf.get(index);
+ }
+
+ @Override
+ public Object getObject(int index) {
+ return (int)(0x0ff & buf.get(index));
+ }
+
+ @Override
+ public boolean has(int index) {
+ return index > -1 && index < buf.capacity();
+ }
+
+ @Override
+ public boolean canDelete(final int index, final boolean strict) {
+ return false;
+ }
+
+ @Override
+ public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+ return false;
+ }
+
+ @Override
+ public ArrayData delete(int index) {
+ throw unsupported("delete");
+ }
+
+ @Override
+ public ArrayData delete(long fromIndex, long toIndex) {
+ throw unsupported("delete");
+ }
+
+ @Override
+ public ArrayData push(final boolean strict, final Object... items) {
+ throw unsupported("push");
+ }
+
+ @Override
+ public Object pop() {
+ throw unsupported("pop");
+ }
+
+ @Override
+ public ArrayData slice(long from, long to) {
+ throw unsupported("slice");
+ }
+
+ @Override
+ public ArrayData convert(final Class<?> type) {
+ throw unsupported("convert");
+ }
+
+ private UnsupportedOperationException unsupported(final String method) {
+ return new UnsupportedOperationException(method);
+ }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
index a1f772b..e15541d 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.runtime.arrays;
+import jdk.nashorn.internal.objects.Global;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
/**
@@ -44,7 +44,7 @@
}
@Override
- public PropertyDescriptor getDescriptor(final GlobalObject global, final int index) {
+ public PropertyDescriptor getDescriptor(final Global global, final int index) {
return global.newDataDescriptor(getObject(index), false, true, false);
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
index 6f77ddc..bc6de9f 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.runtime.arrays;
+import jdk.nashorn.internal.objects.Global;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
/**
@@ -62,7 +62,7 @@
}
@Override
- public PropertyDescriptor getDescriptor(final GlobalObject global, final int index) {
+ public PropertyDescriptor getDescriptor(final Global global, final int index) {
return global.newDataDescriptor(getObject(index), false, true, true);
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
index 96819df..36882e2 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -64,6 +64,7 @@
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -134,6 +135,7 @@
static final Type CONTEXT_TYPE = Type.getType(Context.class);
static final Type OBJECT_TYPE = Type.getType(Object.class);
static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
+ static final Type GLOBAL_TYPE = Type.getType(Global.class);
static final String CONTEXT_TYPE_NAME = CONTEXT_TYPE.getInternalName();
static final String OBJECT_TYPE_NAME = OBJECT_TYPE.getInternalName();
@@ -143,8 +145,10 @@
static final String GLOBAL_FIELD_NAME = "global";
static final String SCRIPT_OBJECT_TYPE_DESCRIPTOR = SCRIPT_OBJECT_TYPE.getDescriptor();
+ static final String GLOBAL_TYPE_DESCRIPTOR = GLOBAL_TYPE.getDescriptor();
- static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, SCRIPT_OBJECT_TYPE);
+
+ static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, GLOBAL_TYPE);
static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
@@ -167,7 +171,7 @@
private static final String UNSUPPORTED_OPERATION_TYPE_NAME = UNSUPPORTED_OPERATION_TYPE.getInternalName();
private static final String METHOD_HANDLE_TYPE_DESCRIPTOR = METHOD_HANDLE_TYPE.getDescriptor();
- private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(SCRIPT_OBJECT_TYPE);
+ private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(GLOBAL_TYPE);
private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.getType(Class.class));
// Package used when the adapter can't be defined in the adaptee's package (either because it's sealed, or because
@@ -259,7 +263,7 @@
}
private void generateGlobalFields() {
- cw.visitField(ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0), GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, null).visitEnd();
+ cw.visitField(ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0), GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR, null, null).visitEnd();
usedFieldNames.add(GLOBAL_FIELD_NAME);
}
@@ -321,7 +325,7 @@
final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_STATIC, CLASS_INIT,
Type.getMethodDescriptor(Type.VOID_TYPE), null, null));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR, false);
final Label initGlobal;
if(samName != null) {
// If the class is a SAM, allow having a ScriptFunction passed as class overrides
@@ -337,7 +341,7 @@
if(mi.getName().equals(samName)) {
mv.dup();
mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR, false);
} else {
mv.visitInsn(ACONST_NULL);
}
@@ -354,7 +358,7 @@
mv.dup();
mv.aconst(mi.getName());
mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false);
mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
@@ -363,7 +367,7 @@
}
// Assign "global = Context.getGlobal()"
invokeGetGlobalWithNullCheck(mv);
- mv.putstatic(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
+ mv.putstatic(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
endInitMethod(mv);
}
@@ -371,7 +375,7 @@
private static void invokeGetGlobalWithNullCheck(final InstructionAdapter mv) {
invokeGetGlobal(mv);
mv.dup();
- mv.invokevirtual(OBJECT_TYPE_NAME, "getClass", GET_CLASS_METHOD_DESCRIPTOR); // check against null Context
+ mv.invokevirtual(OBJECT_TYPE_NAME, "getClass", GET_CLASS_METHOD_DESCRIPTOR, false); // check against null Context
mv.pop();
}
@@ -428,7 +432,7 @@
mv.load(offset, argType);
offset += argType.getSize();
}
- mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor());
+ mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor(), false);
endInitMethod(mv);
}
@@ -481,7 +485,7 @@
mv.load(offset, argType);
offset += argType.getSize();
}
- mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor());
+ mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor(), false);
// Get a descriptor to the appropriate "JavaAdapterFactory.getHandle" method.
final String getHandleDescriptor = fromFunction ? GET_HANDLE_FUNCTION_DESCRIPTOR : GET_HANDLE_OBJECT_DESCRIPTOR;
@@ -500,7 +504,7 @@
mv.aconst(mi.getName());
}
mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor, false);
}
mv.putfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
@@ -508,7 +512,7 @@
// Assign "this.global = Context.getGlobal()"
mv.visitVarInsn(ALOAD, 0);
invokeGetGlobalWithNullCheck(mv);
- mv.putfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
+ mv.putfield(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
endInitMethod(mv);
}
@@ -524,11 +528,11 @@
}
private static void invokeGetGlobal(final InstructionAdapter mv) {
- mv.invokestatic(CONTEXT_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR);
+ mv.invokestatic(CONTEXT_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false);
}
private static void invokeSetGlobal(final InstructionAdapter mv) {
- mv.invokestatic(CONTEXT_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR);
+ mv.invokestatic(CONTEXT_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false);
}
/**
@@ -641,21 +645,21 @@
// If the super method is abstract, throw an exception
mv.anew(UNSUPPORTED_OPERATION_TYPE);
mv.dup();
- mv.invokespecial(UNSUPPORTED_OPERATION_TYPE_NAME, INIT, VOID_NOARG_METHOD_DESCRIPTOR);
+ mv.invokespecial(UNSUPPORTED_OPERATION_TYPE_NAME, INIT, VOID_NOARG_METHOD_DESCRIPTOR, false);
mv.athrow();
} else {
// If the super method is not abstract, delegate to it.
- emitSuperCall(mv, name, methodDesc);
+ emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
}
mv.visitLabel(handleDefined);
// Load the creatingGlobal object
if(classOverride) {
// If class handle is defined, load the static defining global
- mv.getstatic(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
+ mv.getstatic(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
} else {
mv.visitVarInsn(ALOAD, 0);
- mv.getfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
+ mv.getfield(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
}
// stack: [creatingGlobal, handle]
final Label setupGlobal = new Label();
@@ -674,7 +678,7 @@
// stack: [creatingGlobal, creatingGlobal, handle]
// Emit code for switching to the creating global
- // ScriptObject currentGlobal = Context.getGlobal();
+ // Global currentGlobal = Context.getGlobal();
invokeGetGlobal(mv);
mv.dup();
@@ -715,7 +719,7 @@
// Invoke the target method handle
final Label tryBlockStart = new Label();
mv.visitLabel(tryBlockStart);
- mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString());
+ mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString(), false);
final Label tryBlockEnd = new Label();
mv.visitLabel(tryBlockEnd);
emitFinally(mv, currentGlobalVar, globalsDifferVar);
@@ -731,7 +735,7 @@
mv.anew(RUNTIME_EXCEPTION_TYPE);
mv.dupX1();
mv.swap();
- mv.invokespecial(RUNTIME_EXCEPTION_TYPE_NAME, INIT, Type.getMethodDescriptor(Type.VOID_TYPE, THROWABLE_TYPE));
+ mv.invokespecial(RUNTIME_EXCEPTION_TYPE_NAME, INIT, Type.getMethodDescriptor(Type.VOID_TYPE, THROWABLE_TYPE), false);
// Fall through to rethrow handler
} else {
throwableHandler = null;
@@ -744,7 +748,7 @@
final Label methodEnd = new Label();
mv.visitLabel(methodEnd);
- mv.visitLocalVariable("currentGlobal", SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, setupGlobal, methodEnd, currentGlobalVar);
+ mv.visitLocalVariable("currentGlobal", GLOBAL_TYPE_DESCRIPTOR, null, setupGlobal, methodEnd, currentGlobalVar);
mv.visitLocalVariable("globalsDiffer", Type.INT_TYPE.getDescriptor(), null, setupGlobal, methodEnd, globalsDifferVar);
if(throwableDeclared) {
@@ -817,12 +821,12 @@
SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes())));
mv.visitCode();
- emitSuperCall(mv, name, methodDesc);
+ emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
endMethod(mv);
}
- private void emitSuperCall(final InstructionAdapter mv, final String name, final String methodDesc) {
+ private void emitSuperCall(final InstructionAdapter mv, final Class owner, final String name, final String methodDesc) {
mv.visitVarInsn(ALOAD, 0);
int nextParam = 1;
final Type methodType = Type.getMethodType(methodDesc);
@@ -830,7 +834,13 @@
mv.load(nextParam, t);
nextParam += t.getSize();
}
- mv.invokespecial(superClassName, name, methodDesc);
+
+ // default method - non-abstract, interface method
+ if (Modifier.isInterface(owner.getModifiers())) {
+ mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false);
+ } else {
+ mv.invokespecial(superClassName, name, methodDesc, false);
+ }
mv.areturn(methodType.getReturnType());
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
index 5e0b890..475ab08 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
@@ -48,7 +48,6 @@
import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.support.LinkRequestImpl;
-import jdk.nashorn.internal.objects.NativeJava;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.ScriptFunction;
@@ -68,8 +67,8 @@
* generate the adapter class itself; see its documentation for details about the generated class.
* </p><p>
* You normally don't use this class directly, but rather either create adapters from script using
- * {@link NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
- * {@link NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
+ * {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
+ * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
* types.
* </p>
*/
@@ -337,6 +336,7 @@
private static ProtectionDomain createMinimalPermissionDomain() {
// Generated classes need to have at least the permission to access Nashorn runtime and runtime.linker packages.
final Permissions permissions = new Permissions();
+ permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.objects"));
permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime"));
permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime.linker"));
return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
index a8e7918..ca3e10c 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
@@ -29,6 +29,11 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.ref.WeakReference;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -37,10 +42,11 @@
* Constructor of method handles used to guard call sites.
*/
public final class NashornGuards {
- private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class);
- private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
- private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
- private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
+ private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class);
+ private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
+ private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
+ private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class);
+ private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
// don't create me!
private NashornGuards() {
@@ -75,6 +81,55 @@
}
/**
+ * Determine whether the given callsite needs a guard.
+ * @param property the property, or null
+ * @param desc the callsite descriptor
+ * @return true if a guard should be used for this callsite
+ */
+ static boolean needsGuard(final Property property, final CallSiteDescriptor desc) {
+ return property == null || property.isConfigurable()
+ || property.isBound() || !ObjectClassGenerator.OBJECT_FIELDS_ONLY
+ || !NashornCallSiteDescriptor.isFastScope(desc) || property.canChangeType();
+ }
+
+ /**
+ * Get the guard for a property access. This returns an identity guard for non-configurable global properties
+ * and a map guard for everything else.
+ *
+ * @param sobj the first object in the prototype chain
+ * @param property the property
+ * @param desc the callsite descriptor
+ * @return method handle for guard
+ */
+ public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc) {
+ if (!needsGuard(property, desc)) {
+ return null;
+ }
+ if (NashornCallSiteDescriptor.isScope(desc)) {
+ if (property != null && property.isBound()) {
+ // This is a declared top level variables in main script or eval, use identity guard.
+ return getIdentityGuard(sobj);
+ }
+ if (!(sobj instanceof Global) && (property == null || property.isConfigurable())) {
+ // Undeclared variables in nested evals need stronger guards
+ return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap()));
+ }
+ }
+ return getMapGuard(sobj.getMap());
+ }
+
+
+ /**
+ * Get a guard that checks referential identity of the current object.
+ *
+ * @param sobj the self object
+ * @return true if same self object instance
+ */
+ public static MethodHandle getIdentityGuard(final ScriptObject sobj) {
+ return MH.insertArguments(SAME_OBJECT, 1, new WeakReference<>(sobj));
+ }
+
+ /**
* Get a guard that checks if in item is an instance of either of two classes.
*
* @param class1 the first class
@@ -85,6 +140,17 @@
return MH.insertArguments(IS_INSTANCEOF_2, 1, class1, class2);
}
+ /**
+ * Combine two method handles of type {@code (Object)boolean} using logical AND.
+ *
+ * @param guard1 the first guard
+ * @param guard2 the second guard, only invoked if guard1 returns true
+ * @return true if both guard1 and guard2 returned true
+ */
+ public static MethodHandle combineGuards(final MethodHandle guard1, final MethodHandle guard2) {
+ return MH.guardWithTest(guard1, guard2, MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class));
+ }
+
@SuppressWarnings("unused")
private static boolean isScriptObject(final Object self) {
return self instanceof ScriptObject;
@@ -101,6 +167,11 @@
}
@SuppressWarnings("unused")
+ private static boolean sameObject(final Object self, final WeakReference<ScriptObject> ref) {
+ return self == ref.get();
+ }
+
+ @SuppressWarnings("unused")
private static boolean isInstanceOf2(final Object self, final Class<?> class1, final Class<?> class2) {
return class1.isInstance(self) || class2.isInstance(self);
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
index 5cc1cd2..22135bc 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
@@ -37,9 +37,9 @@
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.TypeUtilities;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.GlobalObject;
/**
* Internal linker for String, Boolean, and Number objects, only ever used by Nashorn engine and not exposed to other
@@ -62,7 +62,7 @@
final LinkRequest request = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
final Object self = request.getReceiver();
- final GlobalObject global = (GlobalObject) Context.getGlobal();
+ final Global global = Context.getGlobal();
final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor) request.getCallSiteDescriptor();
return Bootstrap.asType(global.primitiveLookup(request, self), linkerServices, desc);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
index c9b5eaa..7665be7 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
@@ -35,6 +35,7 @@
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.internal.dynalink.support.Guards;
import jdk.nashorn.internal.lookup.Lookup;
+import jdk.nashorn.internal.runtime.FindProperty;
import jdk.nashorn.internal.runtime.ScriptObject;
/**
@@ -61,8 +62,9 @@
* type {@code receiverClass}.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class<?> receiverClass,
- final ScriptObject wrappedReceiver, final MethodHandle wrapFilter) {
- return lookupPrimitive(request, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter);
+ final ScriptObject wrappedReceiver, final MethodHandle wrapFilter,
+ final MethodHandle protoFilter) {
+ return lookupPrimitive(request, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter, protoFilter);
}
/**
@@ -79,7 +81,8 @@
* type (that is implied by both {@code guard} and {@code wrappedReceiver}).
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final MethodHandle guard,
- final ScriptObject wrappedReceiver, final MethodHandle wrapFilter) {
+ final ScriptObject wrappedReceiver, final MethodHandle wrapFilter,
+ final MethodHandle protoFilter) {
final CallSiteDescriptor desc = request.getCallSiteDescriptor();
final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
if ("setProp".equals(operator) || "setElem".equals(operator)) {
@@ -93,9 +96,23 @@
if(desc.getNameTokenCount() > 2) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- if(wrappedReceiver.findProperty(name, true) == null) {
+ final FindProperty find = wrappedReceiver.findProperty(name, true);
+ if(find == null) {
// Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it.
return null;
+ } else if (find.isInherited() && !find.getProperty().hasGetterFunction(find.getOwner())) {
+ // If property is found in the prototype object bind the method handle directly to
+ // the proto filter instead of going through wrapper instantiation below.
+ final ScriptObject proto = wrappedReceiver.getProto();
+ final GuardedInvocation link = proto.lookup(desc, request);
+
+ if (link != null) {
+ final MethodHandle invocation = link.getInvocation();
+ final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class));
+ final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter);
+ final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter);
+ return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard));
+ }
}
}
final GuardedInvocation link = wrappedReceiver.lookup(desc, request);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
index 32f3076..8fc76c1 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
@@ -93,7 +93,8 @@
if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) {
final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) {
- if ("static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
+ if (desc.getNameTokenCount() > CallSiteDescriptor.NAME_OPERAND &&
+ "static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
if (Context.isAccessibleClass((Class<?>)self) && !isReflectionClass((Class<?>)self)) {
// If "getProp:static" passes access checks, allow access.
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
index 95993c9..47248fc 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
@@ -78,6 +78,8 @@
type.error.not.a.function={0} is not a function
type.error.not.a.constructor={0} is not a constructor function
type.error.not.a.file={0} is not a File
+type.error.not.a.bytebuffer={0} is not a java.nio.ByteBuffer
+type.error.not.an.arraybuffer.in.dataview=First arg to DataView constructor must be an ArrayBuffer
# operations not permitted on undefined
type.error.cant.call.undefined=Cannot call undefined
@@ -136,6 +138,9 @@
type.error.method.not.constructor=Java method {0} can't be used as a constructor.
type.error.env.not.object=$ENV must be an Object.
type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
+
+range.error.dataview.constructor.offset=Wrong offset or length in DataView constructor
+range.error.dataview.offset=Offset is outside the bounds of the DataView
range.error.inappropriate.array.length=inappropriate array length: {0}
range.error.inappropriate.array.buffer.length=inappropriate array buffer length: {0}
range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20]
diff --git a/nashorn/src/jdk/nashorn/internal/scripts/JO.java b/nashorn/src/jdk/nashorn/internal/scripts/JO.java
index f2f0006..d617391 100644
--- a/nashorn/src/jdk/nashorn/internal/scripts/JO.java
+++ b/nashorn/src/jdk/nashorn/internal/scripts/JO.java
@@ -33,7 +33,7 @@
*/
public class JO extends ScriptObject {
- private static final PropertyMap map$ = PropertyMap.newMap().setIsShared();
+ private static final PropertyMap map$ = PropertyMap.newMap();
/**
* Returns the initial property map to be used.
diff --git a/nashorn/src/jdk/nashorn/tools/Shell.java b/nashorn/src/jdk/nashorn/tools/Shell.java
index ad19484..ad833d8 100644
--- a/nashorn/src/jdk/nashorn/tools/Shell.java
+++ b/nashorn/src/jdk/nashorn/tools/Shell.java
@@ -42,6 +42,7 @@
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Parser;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
@@ -148,7 +149,7 @@
return COMMANDLINE_ERROR;
}
- final ScriptObject global = context.createGlobal();
+ final Global global = context.createGlobal();
final ScriptEnvironment env = context.getEnv();
final List<String> files = env.getFiles();
if (files.isEmpty()) {
@@ -231,8 +232,8 @@
* @return error code
* @throws IOException when any script file read results in I/O error
*/
- private static int compileScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ private static int compileScripts(final Context context, final Global global, final List<String> files) throws IOException {
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
final ScriptEnvironment env = context.getEnv();
try {
@@ -281,8 +282,8 @@
* @return error code
* @throws IOException when any script file read results in I/O error
*/
- private int runScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ private int runScripts(final Context context, final Global global, final List<String> files) throws IOException {
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
if (globalChanged) {
@@ -339,8 +340,8 @@
* @return error code
* @throws IOException when any script file read results in I/O error
*/
- private static int runFXScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ private static int runFXScripts(final Context context, final Global global, final List<String> files) throws IOException {
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
if (globalChanged) {
@@ -389,11 +390,11 @@
* @return return code
*/
@SuppressWarnings("resource")
- private static int readEvalPrint(final Context context, final ScriptObject global) {
+ private static int readEvalPrint(final Context context, final Global global) {
final String prompt = bundle.getString("shell.prompt");
final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
final PrintWriter err = context.getErr();
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
final ScriptEnvironment env = context.getEnv();
diff --git a/nashorn/test/script/basic/JDK-8011964.js b/nashorn/test/script/basic/JDK-8011964.js
new file mode 100644
index 0000000..a46023e
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8011964.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8011964: need indexed access to externally-managed ByteBuffer
+ *
+ * @test
+ * @run
+ */
+
+
+var ByteBuffer = Java.type("java.nio.ByteBuffer");
+var buf = ByteBuffer.allocate(5);
+
+var obj = {}
+Object.setIndexedPropertiesToExternalArrayData(obj, buf);
+
+obj[0] = 'A'.charCodeAt(0);
+obj[1] = 'B'.charCodeAt(0);
+obj[2] = 'C'.charCodeAt(0);
+obj[3] = 'D'.charCodeAt(0);
+obj[4] = 'E'.charCodeAt(0);
+
+for (var i = 0; i < buf.capacity(); i++) {
+ print("obj[" + i + "] = " + obj[i]);
+ print("buf.get(" + i + ") = " + buf.get(i));
+}
+
+var arr = [];
+Object.setIndexedPropertiesToExternalArrayData(arr, buf);
+obj[0] = 'a'.charCodeAt(0);
+obj[1] = 'b'.charCodeAt(0);
+obj[2] = 'c'.charCodeAt(0);
+obj[3] = 'd'.charCodeAt(0);
+obj[4] = 'e'.charCodeAt(0);
+
+for (var i in arr) {
+ print("arr[" + i + "] = " + arr[i]);
+ print("buf.get(" + i + ") = " + buf.get(i));
+}
diff --git a/nashorn/test/script/basic/JDK-8011964.js.EXPECTED b/nashorn/test/script/basic/JDK-8011964.js.EXPECTED
new file mode 100644
index 0000000..5bec2bd
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8011964.js.EXPECTED
@@ -0,0 +1,20 @@
+obj[0] = 65
+buf.get(0) = 65
+obj[1] = 66
+buf.get(1) = 66
+obj[2] = 67
+buf.get(2) = 67
+obj[3] = 68
+buf.get(3) = 68
+obj[4] = 69
+buf.get(4) = 69
+arr[0] = 97
+buf.get(0) = 97
+arr[1] = 98
+buf.get(1) = 98
+arr[2] = 99
+buf.get(2) = 99
+arr[3] = 100
+buf.get(3) = 100
+arr[4] = 101
+buf.get(4) = 101
diff --git a/nashorn/test/script/basic/JDK-8025515.js b/nashorn/test/script/basic/JDK-8025515.js
index f3d7cee..29574d2 100644
--- a/nashorn/test/script/basic/JDK-8025515.js
+++ b/nashorn/test/script/basic/JDK-8025515.js
@@ -30,13 +30,23 @@
// Make sure synthetic names of anonymous functions have correct line numbers
+function getFirstScriptFrame(stack) {
+ for (frameNum in stack) {
+ var frame = stack[frameNum];
+ if (frame.className.startsWith("jdk.nashorn.internal.scripts.Script$")) {
+ return frame;
+ }
+ }
+}
+
function testMethodName(f, expected) {
try {
f();
fail("expected error");
} catch (e) {
- var stack = e.getStackTrace();
- if (stack[0].methodName !== expected) {
+ var stack = e.nashornException.getStackTrace();
+ var name = getFirstScriptFrame(stack).methodName;
+ if (name !== expected) {
fail("got " + stack[0].methodName + ", expected " + expected);
}
}
@@ -44,15 +54,15 @@
testMethodName(function() {
return a.b.c;
-}, "_L45");
+}, "L:55");
-testMethodName(function() { throw new Error() }, "_L49");
+testMethodName(function() { throw new Error() }, "L:59");
var f = (function() {
return function() { a.b.c; };
})();
-testMethodName(f, "_L51$_L52");
+testMethodName(f, "L:61$L:62");
testMethodName((function() {
return function() { return a.b.c; };
-})(), "_L56$_L57");
+})(), "L:66$L:67");
diff --git a/nashorn/test/script/basic/JDK-8029364.js b/nashorn/test/script/basic/JDK-8029364.js
new file mode 100644
index 0000000..dfa8ea9
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8029364.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, 2013, 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.
+ */
+
+/**
+ * JDK-8029364: NashornException to expose thrown object
+ *
+ * @test
+ * @run
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+var g = e.eval("this");
+try {
+ e.eval("var e = new Error('foo'); e.bar = 33; throw e");
+} catch (se) {
+ // ScriptException instance's cause is a NashornException
+ print(se.getClass());
+ var cause = se.cause;
+ print(cause.getClass());
+ // NashornException instance has 'ecmaError' bean getter
+ print(cause.ecmaError);
+ // access to underlying ECMA Error object
+ print(cause.ecmaError instanceof g.Error);
+ print(cause.ecmaError.name);
+ print(cause.ecmaError.message);
+ print(cause.ecmaError.bar);
+}
+
diff --git a/nashorn/test/script/basic/JDK-8029364.js.EXPECTED b/nashorn/test/script/basic/JDK-8029364.js.EXPECTED
new file mode 100644
index 0000000..d01bb9e
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8029364.js.EXPECTED
@@ -0,0 +1,7 @@
+class javax.script.ScriptException
+class jdk.nashorn.internal.runtime.ECMAException
+Error: foo
+true
+Error
+foo
+33
diff --git a/nashorn/test/script/basic/JDK-8029667.js b/nashorn/test/script/basic/JDK-8029667.js
new file mode 100644
index 0000000..c0c2d15
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8029667.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010, 2013, 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.
+ */
+
+/**
+ * JDK-8029667: Prototype linking is incorrect
+ *
+ * @test
+ * @run
+ */
+
+function f(x) {
+ return (function inner() {
+ var y; (function dummy() { return y })() // force own scope for the inner function
+ with({}) { // 'with' block turns off fast scopes
+ return x
+ }
+ })();
+}
+print(f(1));
+print(f(2));
+
+function g(x) {
+ (function inner() {
+ var y; (function dummy() { return y })() // force own scope for the inner function
+ with({}) { // 'with' block turns off fast scopes
+ // Test setter as well as getter
+ x = x + 2;
+ }
+ })();
+ print(x);
+}
+
+g(1);
+g(2);
+
+var withScopes = [{ func: function() { print("called 1");} }, { func: function() { print("called 2");} }];
+
+for(var i in withScopes) {
+ with (withScopes[i]) {
+ var main = function() {
+ var frame; // <---- this local variable caused scope to be not set properly prior to fix
+
+ function callFunc() {
+ frame = func();
+ }
+
+ callFunc();
+ }
+ }
+ main();
+}
+
+for(var i in withScopes) {
+ with (withScopes[i]) {
+ var main = function() {
+ var frame; // <---- this local variable caused scope to be not set properly prior to fix
+
+ function callFunc() {
+ frame = func = i;
+ }
+
+ callFunc();
+ }
+ }
+ main();
+}
+
+print(withScopes[0].func);
+print(withScopes[1].func);
+
+
diff --git a/nashorn/test/script/basic/JDK-8029667.js.EXPECTED b/nashorn/test/script/basic/JDK-8029667.js.EXPECTED
new file mode 100644
index 0000000..8aa78ef
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8029667.js.EXPECTED
@@ -0,0 +1,8 @@
+1
+2
+3
+4
+called 1
+called 2
+0
+1
diff --git a/nashorn/test/script/basic/JDK-8030182.js b/nashorn/test/script/basic/JDK-8030182.js
new file mode 100644
index 0000000..f3c492d
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8030182.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 2013, 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.
+ */
+
+/**
+ * JDK-8030182: scopeCall with -1 as line number
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+ throw new Error("Strange...");
+}
+
+var f2 = func;
+var f3 = func;
+var f4 = func;
+var f5 = func;
+
+// check that "scopeCall" or some such internal method
+// does not appear in script stack trace.
+try {
+ func();
+} catch(err) {
+ print(err.stack.replace(/\\/g, '/'));
+}
diff --git a/nashorn/test/script/basic/JDK-8030182.js.EXPECTED b/nashorn/test/script/basic/JDK-8030182.js.EXPECTED
new file mode 100644
index 0000000..d12b6d7
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8030182.js.EXPECTED
@@ -0,0 +1,3 @@
+Error: Strange...
+ at func (test/script/basic/JDK-8030182.js:32)
+ at <program> (test/script/basic/JDK-8030182.js:43)
diff --git a/nashorn/test/script/basic/JDK-8030182_2.js b/nashorn/test/script/basic/JDK-8030182_2.js
new file mode 100644
index 0000000..de507e1
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8030182_2.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 2013, 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.
+ */
+
+/**
+ * JDK-8030182: scopeCall with -1 as line number
+ *
+ * @test
+ * @run
+ */
+
+var str = "";
+
+// large code to force splitting
+for (i = 0; i < 1000; ++i)
+ str +="o = new Object()\n";
+
+str +="g()";
+
+// check that "$split" or some such internal method
+// does not appear in script stack trace!!
+try {
+ eval(str);
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
diff --git a/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED b/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED
new file mode 100644
index 0000000..772e504
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED
@@ -0,0 +1,3 @@
+ReferenceError: "g" is not defined
+ at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>@0:-1)
+ at <program> (test/script/basic/JDK-8030182_2.js:42)
diff --git a/nashorn/test/script/basic/JDK-8030197.js b/nashorn/test/script/basic/JDK-8030197.js
new file mode 100644
index 0000000..366d33d
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8030197.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+
+/**
+ * JDK-8030197: Nashorn: Object.defineProperty() can be lured to change fixed NaN property
+ *
+ * @test
+ * @run
+ */
+
+function str(n) {
+ var a = new Uint8Array(new Float64Array([n]).buffer);
+ return Array.apply(null, a).reduceRight(
+ function(acc, v){
+ return acc + (v < 10 ? "0" : "") + v.toString(16);
+ }, "");
+}
+
+var o = Object.defineProperty({}, "NaN", { value: NaN })
+var str1 = str(o.NaN);
+Object.defineProperty(o, "NaN", { value: 0/0 })
+var str2 = str(o.NaN);
+if (str1 != str2) {
+ fail("NaN bit pattern changed");
+}
diff --git a/nashorn/test/script/basic/JDK-8030809.js b/nashorn/test/script/basic/JDK-8030809.js
new file mode 100644
index 0000000..01c7687
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8030809.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2013, 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.
+ */
+
+/**
+ * JDK-8030809: Anonymous functions should not be shown with internal names in script stack trace
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+ (function() {
+ throw new Error();
+ })();
+}
+
+try {
+ func();
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
diff --git a/nashorn/test/script/basic/JDK-8030809.js.EXPECTED b/nashorn/test/script/basic/JDK-8030809.js.EXPECTED
new file mode 100644
index 0000000..6d2ee69
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8030809.js.EXPECTED
@@ -0,0 +1,4 @@
+Error
+ at <anonymous> (test/script/basic/JDK-8030809.js:33)
+ at func (test/script/basic/JDK-8030809.js:32)
+ at <program> (test/script/basic/JDK-8030809.js:38)
diff --git a/nashorn/test/script/basic/JDK-8031317.js b/nashorn/test/script/basic/JDK-8031317.js
new file mode 100644
index 0000000..240a633
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8031317.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2013, 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.
+ */
+
+/**
+ * JDK-8031317: SyntaxError when property setter has no parameter
+ *
+ * @test
+ * @run
+ */
+
+var obj = {
+ get toto() {
+ print("in getter for 'toto'");
+ },
+ set toto() {
+ print("in setter for 'toto'");
+ }
+}
+
+obj.toto;
+obj.toto = 344;
diff --git a/nashorn/test/script/basic/JDK-8031317.js.EXPECTED b/nashorn/test/script/basic/JDK-8031317.js.EXPECTED
new file mode 100644
index 0000000..dda72ea
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8031317.js.EXPECTED
@@ -0,0 +1,2 @@
+in getter for 'toto'
+in setter for 'toto'
diff --git a/nashorn/test/script/basic/JDK-8031359.js b/nashorn/test/script/basic/JDK-8031359.js
new file mode 100644
index 0000000..278fd7d
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8031359.js
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+/**
+ * JDK-8031359: Invocable.getInterface() works incorrectly if interface has default methods
+ *
+ * @test
+ * @run
+ */
+
+var func = new java.util.function.Function() {
+ apply: function(arg) {
+ print("func called with " + arg);
+ return arg.toUpperCase();
+ }
+};
+
+// Function.andThen is a default method
+func.andThen(func)("hello");
+
+// Function.compose is another default method
+func.compose(new java.util.function.Function() {
+ apply: function(arg) {
+ print("compose called with " + arg);
+ return arg.charAt(0);
+ }
+})("hello");
+
+var func2 = new java.util.function.Function() {
+ apply: function(arg) {
+ print("I am func2: " + arg);
+ return arg;
+ },
+
+ andThen: function(func) {
+ print("This is my andThen!");
+ return func;
+ }
+};
+
+func2.apply("hello");
+func2.andThen(func);
diff --git a/nashorn/test/script/basic/JDK-8031359.js.EXPECTED b/nashorn/test/script/basic/JDK-8031359.js.EXPECTED
new file mode 100644
index 0000000..3fb72f1
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8031359.js.EXPECTED
@@ -0,0 +1,6 @@
+func called with hello
+func called with HELLO
+compose called with hello
+func called with h
+I am func2: hello
+This is my andThen!
diff --git a/nashorn/test/script/basic/JDK-8031715.js b/nashorn/test/script/basic/JDK-8031715.js
new file mode 100644
index 0000000..19994f5
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8031715.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8031715: Indexed access to java package not working
+ * @test
+ * @run
+ */
+
+print(java["net"]);
+print(java["net"]["URL"]);
+print(java["net"].URL);
+print(java.net["URL"]);
+
+var is = "InputStream";
+var io = "io";
+
+print(java.io[is]);
+print(java[io]);
+print(java[io][is]);
+
+var ji = new JavaImporter(java.util, java.io);
+print(ji["InputStream"]);
+print(ji['Vector']);
+
+var hash = "Hashtable";
+var printStream = "PrintStream";
+print(ji[hash]);
+print(ji[printStream]);
diff --git a/nashorn/test/script/basic/JDK-8031715.js.EXPECTED b/nashorn/test/script/basic/JDK-8031715.js.EXPECTED
new file mode 100644
index 0000000..1a71de3
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8031715.js.EXPECTED
@@ -0,0 +1,11 @@
+[JavaPackage java.net]
+[JavaClass java.net.URL]
+[JavaClass java.net.URL]
+[JavaClass java.net.URL]
+[JavaClass java.io.InputStream]
+[JavaPackage java.io]
+[JavaClass java.io.InputStream]
+[JavaClass java.io.InputStream]
+[JavaClass java.util.Vector]
+[JavaClass java.util.Hashtable]
+[JavaClass java.io.PrintStream]
diff --git a/nashorn/test/script/basic/JDK-8031983.js b/nashorn/test/script/basic/JDK-8031983.js
new file mode 100644
index 0000000..f0bfca1
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8031983.js
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8031983: Error objects should capture stack at the constructor
+ *
+ * @test
+ * @run
+ */
+
+var e = new Error();
+print("hello");
+
+try {
+ throw e;
+} catch (e) {
+ print(e.lineNumber);
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+Error.captureStackTrace(e);
+try {
+ throw e;
+} catch (e) {
+ print(e.lineNumber);
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+var obj = {};
+Error.captureStackTrace(obj);
+try {
+ throw obj;
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
diff --git a/nashorn/test/script/basic/JDK-8031983.js.EXPECTED b/nashorn/test/script/basic/JDK-8031983.js.EXPECTED
new file mode 100644
index 0000000..9d62db3
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8031983.js.EXPECTED
@@ -0,0 +1,9 @@
+hello
+35
+Error
+ at <program> (test/script/basic/JDK-8031983.js:31)
+43
+Error
+ at <program> (test/script/basic/JDK-8031983.js:41)
+[object Object]
+ at <program> (test/script/basic/JDK-8031983.js:50)
diff --git a/nashorn/test/script/basic/JDK-8032004.js b/nashorn/test/script/basic/JDK-8032004.js
new file mode 100644
index 0000000..2995566
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8032004.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8032004: instance property "message" of Error objects should be non-enumerable
+ *
+ * @test
+ * @run
+ */
+
+function check(obj) {
+ if (obj.propertyIsEnumerable("message")) {
+ fail(obj.name + " object's message property is enumerable!");
+ }
+}
+
+check(new Error("test"));
+check(new EvalError("test"));
+check(new RangeError("test"));
+check(new ReferenceError("test"));
+check(new SyntaxError("test"));
+check(new TypeError("test"));
+check(new URIError("test"));
diff --git a/nashorn/test/script/basic/JDK-8032068.js b/nashorn/test/script/basic/JDK-8032068.js
new file mode 100644
index 0000000..570789d
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8032068.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8032068: implement @sourceURL and #sourceURL directives.
+ *
+ * @test
+ * @run
+ */
+
+
+try {
+ Function("throw new Error();\n//# sourceURL=foo.js")();
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+try {
+ eval("function g() { throw Error('x');\n } g();\n//# sourceURL=bar.js");
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+// check @sourceURL for compatibility
+try {
+ Function("throw new Error();\n//@ sourceURL=foo2.js")();
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+try {
+ eval("function g() { throw Error('x');\n } g();\n//@ sourceURL=bar2.js");
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
diff --git a/nashorn/test/script/basic/JDK-8032068.js.EXPECTED b/nashorn/test/script/basic/JDK-8032068.js.EXPECTED
new file mode 100644
index 0000000..b8891ee
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8032068.js.EXPECTED
@@ -0,0 +1,14 @@
+Error
+ at <anonymous> (foo.js:2)
+ at <program> (test/script/basic/JDK-8032068.js:33)
+Error: x
+ at g (bar.js:1)
+ at <program> (bar.js:2)
+ at <program> (test/script/basic/JDK-8032068.js:39)
+Error
+ at <anonymous> (foo2.js:2)
+ at <program> (test/script/basic/JDK-8032068.js:46)
+Error: x
+ at g (bar2.js:1)
+ at <program> (bar2.js:2)
+ at <program> (test/script/basic/JDK-8032068.js:52)
diff --git a/nashorn/test/script/basic/JDK-8034055.js b/nashorn/test/script/basic/JDK-8034055.js
new file mode 100644
index 0000000..0a21d9f
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8034055.js
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+/**
+ * JDK-8034055: delete on global object not properly guarded
+ *
+ * @test
+ * @run
+ */
+
+
+var global = this;
+var x;
+
+function test(defineGlobals) {
+ if (defineGlobals) {
+ global.x = 1;
+ global.y = 2;
+ }
+ try {
+ print(x);
+ print(y);
+ } catch (e) {
+ print(e);
+ } finally {
+ print(delete global.x);
+ print(delete global.y);
+ }
+}
+
+// Repeatedly set and delete global variables
+test(true);
+test(false);
+test(true);
+test(false);
diff --git a/nashorn/test/script/basic/JDK-8034055.js.EXPECTED b/nashorn/test/script/basic/JDK-8034055.js.EXPECTED
new file mode 100644
index 0000000..c947f4a
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8034055.js.EXPECTED
@@ -0,0 +1,16 @@
+1
+2
+false
+true
+1
+ReferenceError: "y" is not defined
+false
+true
+1
+2
+false
+true
+1
+ReferenceError: "y" is not defined
+false
+true
diff --git a/nashorn/test/script/basic/JDK-8037562.js b/nashorn/test/script/basic/JDK-8037562.js
new file mode 100644
index 0000000..7534a0d
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8037562.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+
+/**
+ * JDK-8037562: Nashorn: JSON.parse comes up with nonexistent entries if there are gaps between the keys
+ *
+ * @test
+ * @run
+ */
+
+var strs = [
+ '{ "0":0, "2":2 }',
+ '{ "0":"", "2":"" }',
+ '{ "0":0, "5":"hello" }',
+ '{ "0":"", "15":3234 }',
+]
+
+for (var i in strs) {
+ print(JSON.stringify(JSON.parse(strs[i])));
+}
diff --git a/nashorn/test/script/basic/JDK-8037562.js.EXPECTED b/nashorn/test/script/basic/JDK-8037562.js.EXPECTED
new file mode 100644
index 0000000..ea67171
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8037562.js.EXPECTED
@@ -0,0 +1,4 @@
+{"0":0,"2":2}
+{"0":"","2":""}
+{"0":0,"5":"hello"}
+{"0":"","15":3234}
diff --git a/nashorn/test/script/basic/NASHORN-111.js.EXPECTED b/nashorn/test/script/basic/NASHORN-111.js.EXPECTED
index 287f255..0967ef4 100644
--- a/nashorn/test/script/basic/NASHORN-111.js.EXPECTED
+++ b/nashorn/test/script/basic/NASHORN-111.js.EXPECTED
@@ -1 +1 @@
-{"message":"type error"}
+{}
diff --git a/nashorn/test/script/basic/NASHORN-441.js.EXPECTED b/nashorn/test/script/basic/NASHORN-441.js.EXPECTED
index de9ea22..c003842 100644
--- a/nashorn/test/script/basic/NASHORN-441.js.EXPECTED
+++ b/nashorn/test/script/basic/NASHORN-441.js.EXPECTED
@@ -12,6 +12,6 @@
try 5
rethrow 5
finally 5
-Error: try 5 thrown in line 71
+Error: try 5 thrown in line 74
try 6
finally 6
diff --git a/nashorn/test/script/basic/dataview_endian.js b/nashorn/test/script/basic/dataview_endian.js
new file mode 100644
index 0000000..f7607c0
--- /dev/null
+++ b/nashorn/test/script/basic/dataview_endian.js
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8015958: DataView constructor is not defined
+ *
+ * @test
+ * @run
+ */
+
+// set/get endianess checks
+
+var buffer = new ArrayBuffer(4);
+var dv = new DataView(buffer);
+
+// write (default) big endian, read big/little endian
+dv.setUint16(0, 0xABCD);
+Assert.assertEquals(dv.getUint16(0), 0xABCD);
+Assert.assertEquals(dv.getUint16(0, false), 0xABCD);
+Assert.assertEquals(dv.getUint16(0, true), 0xCDAB);
+
+// write little endian, read big/little endian
+dv.setUint16(0, 0xABCD, true);
+Assert.assertEquals(dv.getUint16(0), 0xCDAB);
+Assert.assertEquals(dv.getUint16(0, false), 0xCDAB);
+Assert.assertEquals(dv.getUint16(0, true), 0xABCD);
+
+// write explicit big endian, read big/little endian
+dv.setUint16(0, 0xABCD, false);
+Assert.assertEquals(dv.getUint16(0), 0xABCD);
+Assert.assertEquals(dv.getUint16(0, false), 0xABCD);
+Assert.assertEquals(dv.getUint16(0, true), 0xCDAB);
+
+// write (default) big endian, read big/little endian
+dv.setUint32(0, 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0), 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0, false), 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0, true), 0x89EFCDAB);
+
+// write little endian, read big/little endian
+dv.setUint32(0, 0xABCDEF89, true);
+Assert.assertEquals(dv.getUint32(0), 0x89EFCDAB);
+Assert.assertEquals(dv.getUint32(0, false), 0x89EFCDAB);
+Assert.assertEquals(dv.getUint32(0, true), 0xABCDEF89);
+
+// write explicit big endian, read big/little endian
+dv.setUint32(0, 0xABCDEF89, false);
+Assert.assertEquals(dv.getUint32(0), 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0, false), 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0, true), 0x89EFCDAB);
diff --git a/nashorn/test/script/basic/dataview_getset.js b/nashorn/test/script/basic/dataview_getset.js
new file mode 100644
index 0000000..8c7a994
--- /dev/null
+++ b/nashorn/test/script/basic/dataview_getset.js
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8015958: DataView constructor is not defined
+ *
+ * @test
+ * @run
+ */
+
+// checking get/set of values of various types
+// Also basic endianess check.
+
+var Float = Java.type("java.lang.Float");
+var Double = Java.type("java.lang.Double");
+
+var DOUBLE_MIN = Double.MIN_VALUE;
+var DOUBLE_MIN_NORMAL = Double.MIN_NORMAL;
+var FLOAT_MIN = Float.MIN_VALUE;
+var FLOAT_MIN_NORMAL = Float.MIN_NORMAL;
+
+var buffer = new ArrayBuffer(12);
+var dv = new DataView(buffer);
+
+dv.setInt8(1, 123);
+Assert.assertEquals(dv.getInt8(1), 123);
+dv.setInt8(1, 123, true);
+Assert.assertEquals(dv.getInt8(1, true), 123);
+
+dv.setUint8(1, 255);
+Assert.assertEquals(dv.getUint8(1), 255);
+dv.setUint8(1, 255, true);
+Assert.assertEquals(dv.getUint8(1, true), 255);
+
+dv.setInt16(1, 1234);
+Assert.assertEquals(dv.getInt16(1), 1234);
+dv.setInt16(1, 1234, true);
+Assert.assertEquals(dv.getInt16(1, true), 1234);
+
+dv.setUint16(1, 65535);
+Assert.assertEquals(dv.getUint16(1), 65535);
+dv.setUint16(1, 65535, true);
+Assert.assertEquals(dv.getUint16(1, true), 65535);
+
+dv.setInt32(1, 1234);
+Assert.assertEquals(dv.getInt32(1), 1234);
+dv.setInt32(1, 1234, true);
+Assert.assertEquals(dv.getInt32(1, true), 1234);
+
+dv.setUint32(1, 4294967295);
+Assert.assertEquals(dv.getUint32(1), 4294967295);
+dv.setUint32(1, 4294967295, true);
+Assert.assertEquals(dv.getUint32(1, true), 4294967295);
+
+dv.setFloat64(1, Math.PI);
+Assert.assertEquals(dv.getFloat64(1), Math.PI, DOUBLE_MIN);
+dv.setFloat64(1, Math.PI, true);
+Assert.assertEquals(dv.getFloat64(1, true), Math.PI, DOUBLE_MIN);
+
+dv.setFloat64(1, DOUBLE_MIN_NORMAL);
+Assert.assertEquals(dv.getFloat64(1), DOUBLE_MIN_NORMAL, DOUBLE_MIN);
+dv.setFloat64(1, DOUBLE_MIN_NORMAL, true);
+Assert.assertEquals(dv.getFloat64(1, true), DOUBLE_MIN_NORMAL, DOUBLE_MIN);
+
+dv.setFloat32(1, 1.414);
+Assert["assertEquals(float, float, float)"](dv.getFloat32(1), 1.414, FLOAT_MIN);
+dv.setFloat32(1, 1.414, true);
+Assert["assertEquals(float, float, float)"](dv.getFloat32(1, true), 1.414, FLOAT_MIN);
+
+dv.setFloat32(1, FLOAT_MIN_NORMAL);
+Assert["assertEquals(float, float, float)"](dv.getFloat32(1), FLOAT_MIN_NORMAL, FLOAT_MIN);
+dv.setFloat32(1, FLOAT_MIN_NORMAL, true);
+Assert["assertEquals(float, float, float)"](dv.getFloat32(1, true), FLOAT_MIN_NORMAL, FLOAT_MIN);
diff --git a/nashorn/test/script/basic/dataview_new.js b/nashorn/test/script/basic/dataview_new.js
new file mode 100644
index 0000000..78f8183
--- /dev/null
+++ b/nashorn/test/script/basic/dataview_new.js
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8015958: DataView constructor is not defined
+ *
+ * @test
+ * @run
+ */
+
+// basic DataView constructor checks.
+
+// check ArrayBufferView property values of DataView instance
+function check(dv, buf, offset, length) {
+ if (dv.buffer !== buf) {
+ fail("DataView.buffer is wrong");
+ }
+
+ if (dv.byteOffset != offset) {
+ fail("DataView.byteOffset = " + dv.byteOffset + ", expected " + offset);
+ }
+
+ if (dv.byteLength != length) {
+ fail("DataView.byteLength = " + dv.byteLength + ", expected " + length);
+ }
+}
+
+var buffer = new ArrayBuffer(12);
+check(new DataView(buffer), buffer, 0, 12);
+check(new DataView(buffer, 2), buffer, 2, 10);
+check(new DataView(buffer, 4, 8), buffer, 4, 8);
+
+// make sure expected error is thrown
+function checkError(callback, ErrorType) {
+ try {
+ callback();
+ fail("Should have thrown " + ErrorType.name);
+ } catch (e) {
+ if (! (e instanceof ErrorType)) {
+ fail("Expected " + ErrorType.name + " got " + e);
+ }
+ }
+}
+
+// non ArrayBuffer as first arg
+checkError(function() { new DataView(344) }, TypeError);
+
+// illegal offset/length values
+checkError(function() { new DataView(buffer, -1) }, RangeError);
+checkError(function() { new DataView(buffer, 15) }, RangeError);
+checkError(function() { new DataView(buffer, 1, 32) }, RangeError);
diff --git a/nashorn/test/script/currently-failing/gettersetter.js b/nashorn/test/script/currently-failing/gettersetter.js
new file mode 100644
index 0000000..88f6949
--- /dev/null
+++ b/nashorn/test/script/currently-failing/gettersetter.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+function Foo() {
+ return {
+ get foo() { return 42; },
+ set foo(x) {}
+ }
+}
+
+var obj1 = Foo();
+var obj2 = Foo();
+
+assertSameMap(obj1, obj2, "Object literals before change");
+
+Object.defineProperty(obj2, "foo", { get: function() { return 'hello' } });
+assertSameMap(obj1, obj2);
+
+Object.defineProperty(obj2, "foo", { set: function(x) { print(x) } });
+assertSameMap(obj1, obj2);
diff --git a/nashorn/test/script/error/JDK-8039047.js b/nashorn/test/script/error/JDK-8039047.js
new file mode 100644
index 0000000..8cbd51f
--- /dev/null
+++ b/nashorn/test/script/error/JDK-8039047.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8039047: Parser accepts conditional catch clauses even when --no-syntax-extensions / -nse option is passed
+ *
+ * @option --no-syntax-extensions
+ * @test/compile-error
+ */
+
+try {
+ func()
+} catch (e if e instanceof ReferenceError) {
+ print("Got ReferenceError " + e);
+}
diff --git a/nashorn/test/script/error/JDK-8039047.js.EXPECTED b/nashorn/test/script/error/JDK-8039047.js.EXPECTED
new file mode 100644
index 0000000..b1d2f17
--- /dev/null
+++ b/nashorn/test/script/error/JDK-8039047.js.EXPECTED
@@ -0,0 +1,6 @@
+test/script/error/JDK-8039047.js:33:11 Expected ) but found if
+} catch (e if e instanceof ReferenceError) {
+ ^
+test/script/error/JDK-8039047.js:35:0 Expected eof but found }
+}
+^
diff --git a/nashorn/test/script/maptests/builtins.js b/nashorn/test/script/maptests/builtins.js
new file mode 100644
index 0000000..4de2ec9
--- /dev/null
+++ b/nashorn/test/script/maptests/builtins.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+// check that builtin objects share property map
+
+assertSameMap(new Boolean(true), new Boolean(false));
+assertSameMap(new Number(3), new Number(Math.PI));
+assertSameMap(new String('hello'), new String('world'));
+assertSameMap(new Object(), new Object());
+assertSameMap(/hello/, /world/);
+// try w/without regexp flags
+assertSameMap(/hello/i, /world/g);
+assertSameMap(new Date(), new Date());
+assertSameMap(new Date(2000, 1, 1), new Date(1972, 5, 6));
+assertSameMap(Function(), Function());
+assertSameMap(Function("x", "return x"), Function("x", "return x*x"));
+assertSameMap(new Error(), new Error());
+assertSameMap(new Error('foo'), new Error('bar'));
+assertSameMap(new EvalError(), new EvalError());
+assertSameMap(new EvalError('foo'), new EvalError('bar'));
+assertSameMap(new RangeError(), new RangeError());
+assertSameMap(new RangeError('foo'), new RangeError('bar'));
+assertSameMap(new ReferenceError(), new ReferenceError());
+assertSameMap(new ReferenceError('foo'), new ReferenceError('bar'));
+assertSameMap(new SyntaxError(), new SyntaxError());
+assertSameMap(new SyntaxError('foo'), new SyntaxError('bar'));
+assertSameMap(new TypeError(), new TypeError());
+assertSameMap(new TypeError('foo'), new TypeError('bar'));
+assertSameMap(new URIError(), new URIError());
+assertSameMap(new URIError('foo'), new URIError('bar'));
diff --git a/nashorn/test/script/maptests/constructor.js b/nashorn/test/script/maptests/constructor.js
new file mode 100644
index 0000000..5722a3c
--- /dev/null
+++ b/nashorn/test/script/maptests/constructor.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "point.js");
+
+// use constructor defined in a different script file
+// These objects should share the map
+assertSameMap(new Point(2, 3), new Point(43, 23));
+assertSameMap(new Point(), new Point());
+assertSameMap(new Point(), new Point(3, 1));
diff --git a/nashorn/test/script/maptests/maputil.js b/nashorn/test/script/maptests/maputil.js
new file mode 100644
index 0000000..aa85d7f
--- /dev/null
+++ b/nashorn/test/script/maptests/maputil.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+/**
+ * @subtest
+ */
+
+function assertSameMap(obj1, obj2, msg) {
+ if (! Debug.identical(Debug.map(obj1), Debug.map(obj2))) {
+ fail(obj1.constructor + " instances don't share map");
+ }
+}
+
+function assertNotSameMap(obj1, obj2, msg) {
+ if (Debug.identical(Debug.map(obj1), Debug.map(obj2))) {
+ fail(obj1.constructor + " and " + obj2.constructor + " instances share map");
+ }
+}
diff --git a/nashorn/test/script/maptests/object_create.js b/nashorn/test/script/maptests/object_create.js
new file mode 100644
index 0000000..1b1bd60
--- /dev/null
+++ b/nashorn/test/script/maptests/object_create.js
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+// Objects created by Object.create
+var obj1 = Object.create(Object.prototype);
+var obj2 = Object.create(Object.prototype);
+assertSameMap(obj1, obj2);
+
+var proto = { foo: 233 };
+obj1 = Object.create(proto);
+obj2 = Object.create(proto);
+assertSameMap(obj1, obj2);
diff --git a/nashorn/test/script/maptests/object_literals.js b/nashorn/test/script/maptests/object_literals.js
new file mode 100644
index 0000000..c73d801
--- /dev/null
+++ b/nashorn/test/script/maptests/object_literals.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+// Object literals created at the same callsite
+function makeObject() {
+ return { foo: 34 }
+}
+assertSameMap(makeObject(), makeObject());
+
+function makeObject2() {
+ return { foo: 42, bar: 'hello' }
+}
+assertSameMap(makeObject2(), makeObject2());
+
+// Object literals created at different callsites
+assertSameMap({}, {});
+assertSameMap({foo: 4}, {foo: 'hello'});
+assertSameMap({foo: 34, bar: 'fdgd'}, {foo: 'world', bar: 54});
diff --git a/nashorn/test/script/maptests/point.js b/nashorn/test/script/maptests/point.js
new file mode 100644
index 0000000..38b8fa2
--- /dev/null
+++ b/nashorn/test/script/maptests/point.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+
+/**
+ * @subtest
+ */
+
+function Point(x, y) {
+ this.x =x; this.y =y;
+}
+
+Point.prototype.toString = function() {
+ return "(" + this.x + "," + this.y + ")";
+}
+
+Point.prototype.modulus = function() {
+ return Math.sqrt(this.x*this.x + this.y*this.y);
+}
+
+Point.prototype.argument = function() {
+ return Math.atan2(this.y, this.x);
+}
+
+load(__DIR__ + "maputil.js");
+
+assertSameMap(new Point(2, 3), new Point(43, 23));
+assertSameMap(new Point(), new Point());
+assertSameMap(new Point(), new Point(3, 1));
diff --git a/nashorn/test/script/maptests/property_add.js b/nashorn/test/script/maptests/property_add.js
new file mode 100644
index 0000000..2026455
--- /dev/null
+++ b/nashorn/test/script/maptests/property_add.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+function Foo() {}
+
+var obj1 = new Foo();
+var obj2 = new Foo();
+
+assertSameMap(obj1, obj2);
+
+// property addition at same callsite
+function addX(obj, val) {
+ obj.x = val;
+}
+addX(obj1, 3);
+addX(obj2, 'hello');
+
+assertSameMap(obj1, obj2);
diff --git a/nashorn/test/script/maptests/property_delete.js b/nashorn/test/script/maptests/property_delete.js
new file mode 100644
index 0000000..e2824dd
--- /dev/null
+++ b/nashorn/test/script/maptests/property_delete.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+function Foo() {
+ this.x = 33;
+}
+
+var obj1 = new Foo();
+var obj2 = new Foo();
+
+assertSameMap(obj1, obj2);
+
+// property deletion at same callsite
+function deleteX(obj) {
+ delete obj.x;
+}
+deleteX(obj1);
+deleteX(obj2);
+
+assertSameMap(obj1, obj2);
diff --git a/nashorn/test/script/maptests/proto.js b/nashorn/test/script/maptests/proto.js
new file mode 100644
index 0000000..afb5950
--- /dev/null
+++ b/nashorn/test/script/maptests/proto.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+// add/delete property to proto (direct/indirect) should
+// not affect the property map of the objects
+
+var proto2 = { foo: 334 }
+var proto = Object.create(proto2);
+proto.bar = "hello";
+
+var obj1 = Object.create(proto);
+var obj2 = Object.create(proto);
+
+assertSameMap(obj1, obj2);
+
+proto.newX = 'world';
+assertSameMap(obj1, obj2);
+
+delete proto.newX;
+assertSameMap(obj1, obj2);
+
+proto2.newX = "foo";
+assertSameMap(obj1, obj2);
+
+delete proto2.newX;
+assertSameMap(obj1, obj2);
+
+
diff --git a/nashorn/test/script/sandbox/JDK-8031106.js b/nashorn/test/script/sandbox/JDK-8031106.js
new file mode 100644
index 0000000..d5d83f6
--- /dev/null
+++ b/nashorn/test/script/sandbox/JDK-8031106.js
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+/**
+ * JDK-8031106: Nashorn: IndexOutOfBoundsException in NashornCallSiteDescriptor.getNameToken()
+ *
+ * @test
+ * @run
+ */
+
+var cl = new java.lang.Object().getClass();
+try {
+ cl["forName"];
+ fail("Should have thrown exception!");
+} catch (e) {
+ if (! (e instanceof java.lang.SecurityException)) {
+ fail("SecurityException expected, got " + e);
+ }
+}
diff --git a/nashorn/test/script/sandbox/safeprops.js b/nashorn/test/script/sandbox/safeprops.js
new file mode 100644
index 0000000..dc12e74
--- /dev/null
+++ b/nashorn/test/script/sandbox/safeprops.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+/**
+ * Try to access System properties safe to read for any code.
+ * No security exception expected.
+ *
+ * @test
+ * @security
+ * @run
+ * @bug 8033924: Default permissions are not given for eval code
+ */
+
+var propNames = [
+ "java.version",
+ "java.vendor",
+ "java.vendor.url",
+ "java.class.version",
+ "os.name",
+ "os.version",
+ "os.arch",
+ "file.separator",
+ "path.separator",
+ "line.separator",
+ "java.specification.version",
+ "java.specification.vendor",
+ "java.specification.name",
+ "java.vm.specification.version",
+ "java.vm.specification.vendor",
+ "java.vm.specification.name",
+ "java.vm.version",
+ "java.vm.vendor",
+ "java.vm.name"
+];
+
+// no security exception expected
+for (var p in propNames) {
+ java.lang.System.getProperty(propNames[p]);
+}
+
+// no security exception expected
+for (var p in propNames) {
+ var name = propNames[p];
+ eval('java.lang.System.getProperty(name)');
+}
diff --git a/nashorn/test/script/trusted/JDK-8032060.js b/nashorn/test/script/trusted/JDK-8032060.js
new file mode 100644
index 0000000..8cb350c
--- /dev/null
+++ b/nashorn/test/script/trusted/JDK-8032060.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8032060: PropertyMap of Error objects is not stable
+ *
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ * @run
+ */
+
+function checkMap(e1, e2) {
+ if (! Debug.identical(Debug.map(e1), Debug.map(e2))) {
+ fail("e1 and e2 have different maps");
+ }
+
+ var m1, m2;
+
+ try {
+ throw e1
+ } catch (e) {
+ m1 = Debug.map(e)
+ }
+
+ try {
+ throw e2
+ } catch (e) {
+ m2 = Debug.map(e)
+ }
+
+ if (! Debug.identical(m1, m2)) {
+ fail("e1 and e2 have different maps after being thrown");
+ }
+}
+
+checkMap(new Error(), new Error());
+checkMap(new EvalError(), new EvalError());
+checkMap(new RangeError(), new RangeError());
+checkMap(new ReferenceError(), new ReferenceError());
+checkMap(new SyntaxError(), new SyntaxError());
+checkMap(new TypeError(), new TypeError());
+checkMap(new URIError(), new URIError());
+
+// now try with message param
+checkMap(new Error("x"), new Error("y"));
+checkMap(new EvalError("x"), new EvalError("y"));
+checkMap(new RangeError("x"), new RangeError("y"));
+checkMap(new ReferenceError("x"), new ReferenceError("y"));
+checkMap(new SyntaxError("x"), new SyntaxError("y"));
+checkMap(new TypeError("x"), new TypeError("y"));
+checkMap(new URIError("x"), new URIError("y"));
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java
index fad3f37..a6722f5 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java
@@ -26,6 +26,7 @@
package jdk.nashorn.api.scripting;
import java.util.Objects;
+import java.util.function.Function;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
@@ -522,4 +523,16 @@
Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
}
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void defaultMethodTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Invocable inv = (Invocable) e;
+
+ Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})");
+ Function<String, String> func = inv.getInterface(obj, Function.class);
+ assertEquals(func.apply("hello"), "HELLO");
+ }
}
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java
index a18055b..dc27d82 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java
@@ -245,4 +245,320 @@
sb.put("x", "newX");
assertTrue(e.eval("x", ctx).equals("newX"));
}
+
+ /**
+ * Test multi-threaded access to defined global variables for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedVarTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ final String sharedScript = "foo";
+
+ assertEquals(e.eval("var foo = 'original context';", origContext), null);
+ assertEquals(e.eval("var foo = 'new context';", newCtxt), null);
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ assertEquals(e.eval("var foo = 'newer context';", newCtxt), null);
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+
+ assertEquals(e.eval(sharedScript), "original context");
+ assertEquals(e.eval(sharedScript, newCtxt), "newer context");
+ }
+
+ /**
+ * Test multi-threaded access to undefined global variables for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedGlobalTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ assertEquals(e.eval("foo = 'original context';", origContext), "original context");
+ assertEquals(e.eval("foo = 'new context';", newCtxt), "new context");
+ final String sharedScript = "foo";
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ Object obj3 = e.eval("delete foo; foo = 'newer context';", newCtxt);
+ assertEquals(obj3, "newer context");
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+
+ Assert.assertEquals(e.eval(sharedScript), "original context");
+ Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context");
+ }
+
+ /**
+ * Test multi-threaded access using the postfix ++ operator for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedIncTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ assertEquals(e.eval("var x = 0;", origContext), null);
+ assertEquals(e.eval("var x = 2;", newCtxt), null);
+ final String sharedScript = "x++;";
+
+ final Thread t1 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < 1000; i++) {
+ assertEquals(e.eval(sharedScript, origContext), (double)i);
+ }
+ } catch (ScriptException se) {
+ fail(se.toString());
+ }
+ }
+ });
+ final Thread t2 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ for (int i = 2; i < 1000; i++) {
+ assertEquals(e.eval(sharedScript, newCtxt), (double)i);
+ }
+ } catch (ScriptException se) {
+ fail(se.toString());
+ }
+ }
+ });
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+ }
+
+ /**
+ * Test multi-threaded access to primitive prototype properties for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedPrimitiveTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ Object obj1 = e.eval("String.prototype.foo = 'original context';", origContext);
+ Object obj2 = e.eval("String.prototype.foo = 'new context';", newCtxt);
+ assertEquals(obj1, "original context");
+ assertEquals(obj2, "new context");
+ final String sharedScript = "''.foo";
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+ assertEquals(obj3, "newer context");
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+
+ Assert.assertEquals(e.eval(sharedScript), "original context");
+ Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context");
+ }
+
+ /**
+ * Test multi-threaded scope function invocation for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedFunctionTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/func.js")), origContext);
+ assertEquals(origContext.getAttribute("scopeVar"), 1);
+ assertEquals(e.eval("scopeTest()"), 1);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/func.js")), newCtxt);
+ assertEquals(newCtxt.getAttribute("scopeVar"), 1);
+ assertEquals(e.eval("scopeTest();", newCtxt), 1);
+
+ assertEquals(e.eval("scopeVar = 3;", newCtxt), 3);
+ assertEquals(newCtxt.getAttribute("scopeVar"), 3);
+
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, "scopeTest()", 1, 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, "scopeTest()", 3, 1000));
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ }
+
+ /**
+ * Test multi-threaded access to global getters and setters for shared script classes with multiple globals.
+ */
+ @Test
+ public static void getterSetterTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ final String sharedScript = "accessor1";
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), origContext);
+ assertEquals(e.eval("accessor1 = 1;"), 1);
+ assertEquals(e.eval(sharedScript), 1);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), newCtxt);
+ assertEquals(e.eval("accessor1 = 2;", newCtxt), 2);
+ assertEquals(e.eval(sharedScript, newCtxt), 2);
+
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, 1, 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, 2, 1000));
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ assertEquals(e.eval(sharedScript), 1);
+ assertEquals(e.eval(sharedScript, newCtxt), 2);
+ assertEquals(e.eval("v"), 1);
+ assertEquals(e.eval("v", newCtxt), 2);
+ }
+
+ /**
+ * Test multi-threaded access to global getters and setters for shared script classes with multiple globals.
+ */
+ @Test
+ public static void getterSetter2Test() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ final String sharedScript = "accessor2";
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), origContext);
+ assertEquals(e.eval("accessor2 = 1;"), 1);
+ assertEquals(e.eval(sharedScript), 1);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), newCtxt);
+ assertEquals(e.eval("accessor2 = 2;", newCtxt), 2);
+ assertEquals(e.eval(sharedScript, newCtxt), 2);
+
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, 1, 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, 2, 1000));
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ assertEquals(e.eval(sharedScript), 1);
+ assertEquals(e.eval(sharedScript, newCtxt), 2);
+ assertEquals(e.eval("x"), 1);
+ assertEquals(e.eval("x", newCtxt), 2);
+ }
+
+ /**
+ * Test "slow" scopes involving {@code with} and {@code eval} statements for shared script classes with multiple globals.
+ */
+ @Test
+ public static void testSlowScope() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+
+ for (int i = 0; i < 100; i++) {
+ final Bindings b = e.createBindings();
+ final ScriptContext ctxt = new SimpleScriptContext();
+ ctxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/witheval.js")), ctxt);
+ assertEquals(e.eval("a", ctxt), 1);
+ assertEquals(b.get("a"), 1);
+ assertEquals(e.eval("b", ctxt), 3);
+ assertEquals(b.get("b"), 3);
+ assertEquals(e.eval("c", ctxt), 10);
+ assertEquals(b.get("c"), 10);
+ }
+ }
+
+ private static class ScriptRunner implements Runnable {
+
+ final ScriptEngine engine;
+ final ScriptContext context;
+ final String source;
+ final Object expected;
+ final int iterations;
+
+ ScriptRunner(final ScriptEngine engine, final ScriptContext context, final String source, final Object expected, final int iterations) {
+ this.engine = engine;
+ this.context = context;
+ this.source = source;
+ this.expected = expected;
+ this.iterations = iterations;
+ }
+
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < iterations; i++) {
+ assertEquals(engine.eval(source, context), expected);
+ }
+ } catch (ScriptException se) {
+ throw new RuntimeException(se);
+ }
+ }
+ }
+
}
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
index df8696d..5219914 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
@@ -560,6 +560,47 @@
assertTrue(reached[0]);
}
+ // properties that can be read by any code
+ private static String[] propNames = {
+ "java.version",
+ "java.vendor",
+ "java.vendor.url",
+ "java.class.version",
+ "os.name",
+ "os.version",
+ "os.arch",
+ "file.separator",
+ "path.separator",
+ "line.separator",
+ "java.specification.version",
+ "java.specification.vendor",
+ "java.specification.name",
+ "java.vm.specification.version",
+ "java.vm.specification.vendor",
+ "java.vm.specification.name",
+ "java.vm.version",
+ "java.vm.vendor",
+ "java.vm.name"
+ };
+
+ // @bug 8033924: Default permissions are not given for eval code
+ @Test
+ public void checkPropertyReadPermissions() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+
+ for (final String name : propNames) {
+ checkProperty(e, name);
+ }
+ }
+
+ private static void checkProperty(final ScriptEngine e, final String name)
+ throws ScriptException {
+ String value = System.getProperty(name);
+ e.put("name", name);
+ assertEquals(value, e.eval("java.lang.System.getProperty(name)"));
+ }
+
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
// Returns String that would be the result of calling PrintWriter.println
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
index 544f4ea..241f22c 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
@@ -25,6 +25,7 @@
package jdk.nashorn.api.scripting;
+import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -230,6 +231,29 @@
}
@Test
+ public void indexPropertiesExternalBufferTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final ScriptObjectMirror obj = (ScriptObjectMirror)e.eval("var obj = {}; obj");
+ final ByteBuffer buf = ByteBuffer.allocate(5);
+ int i;
+ for (i = 0; i < 5; i++) {
+ buf.put(i, (byte)(i+10));
+ }
+ obj.setIndexedPropertiesToExternalArrayData(buf);
+
+ for (i = 0; i < 5; i++) {
+ assertEquals((byte)(i+10), ((Number)e.eval("obj[" + i + "]")).byteValue());
+ }
+
+ e.eval("for (i = 0; i < 5; i++) obj[i] = 0");
+ for (i = 0; i < 5; i++) {
+ assertEquals((byte)0, ((Number)e.eval("obj[" + i + "]")).byteValue());
+ assertEquals((byte)0, buf.get(i));
+ }
+ }
+
+ @Test
public void conversionTest() throws ScriptException {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/resources/func.js b/nashorn/test/src/jdk/nashorn/api/scripting/resources/func.js
new file mode 100644
index 0000000..477bd1a
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/resources/func.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse.
+
+var scopeVar = 1;
+var global = this;
+undefGlobal = this;
+
+function scopeTest() {
+ if (this !== global) {
+ throw new Error("this !== global");
+ }
+ if (this !== undefGlobal) {
+ throw new Error("this !== undefinedGlobal")
+ }
+ return scopeVar;
+}
+
+scopeTest();
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/resources/gettersetter.js b/nashorn/test/src/jdk/nashorn/api/scripting/resources/gettersetter.js
new file mode 100644
index 0000000..51e2472
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/resources/gettersetter.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse.
+
+var v;
+
+Object.defineProperty(this, "accessor1", {
+ get: function() { return v; },
+ set: function(n) { v = n; }
+});
+
+Object.defineProperty(this, "accessor2", {
+ get: function() { return x; },
+ set: function(n) { x = n; }
+});
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/resources/witheval.js b/nashorn/test/src/jdk/nashorn/api/scripting/resources/witheval.js
new file mode 100644
index 0000000..6041d5b
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/resources/witheval.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse.
+
+var a;
+
+function outer(p, e) {
+ eval(e);
+ with(p) {
+ function inner() {
+ a = 1;
+ c = 10;
+ if (a !== 1) {
+ throw new Error("a !== 1");
+ }
+ if (b !== 3) {
+ throw new Error("b !== 3");
+ }
+ if (c !== 10) {
+ throw new Error("c !== 10");
+ }
+ }
+ inner();
+ }
+}
+
+outer({}, "b = 3;");
+
+if (a !== 1) {
+ throw new Error("a !== 1");
+}
+if (b !== 3) {
+ throw new Error("b !== 3");
+}
+if (c !== 10) {
+ throw new Error("c !== 10");
+}
diff --git a/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java b/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
index 00d79ac..ac43810 100644
--- a/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
@@ -28,6 +28,7 @@
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.ScriptFunction;
@@ -58,7 +59,7 @@
}
private Context context;
- private ScriptObject global;
+ private Global global;
@BeforeClass
public void setupTest() {
@@ -146,7 +147,7 @@
log("Begin compiling " + file.getAbsolutePath());
}
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
diff --git a/nashorn/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java b/nashorn/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
index 999f6fa..ce96921 100644
--- a/nashorn/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
+++ b/nashorn/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
@@ -31,9 +31,9 @@
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
@@ -89,7 +89,7 @@
@Override
protected Object apply(final ScriptFunction target, final Object self) {
if (_runsPerIteration == 0 && _numberOfIterations == 0) {
- final ScriptObject global = jdk.nashorn.internal.runtime.Context.getGlobal();
+ final Global global = jdk.nashorn.internal.runtime.Context.getGlobal();
final ScriptFunction _target = target;
final Object _self = self;
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java
index 1b21c23..1ec4169 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java
@@ -29,6 +29,7 @@
import static org.testng.Assert.assertTrue;
import java.util.Map;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.options.Options;
import org.testng.annotations.Test;
@@ -45,7 +46,7 @@
final Options options = new Options("");
final ErrorManager errors = new ErrorManager();
final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader());
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
Context.setGlobal(cx.createGlobal());
try {
String code = "22 + 10";
@@ -65,7 +66,7 @@
final ErrorManager errors = new ErrorManager();
final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader());
final boolean strict = cx.getEnv()._strict;
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
Context.setGlobal(cx.createGlobal());
try {
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
index ac2dc17..83d057f 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
@@ -34,10 +34,10 @@
import java.io.OutputStream;
import java.io.PrintWriter;
import jdk.nashorn.api.scripting.NashornException;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.options.Options;
@@ -110,12 +110,12 @@
@Override
public int run(final OutputStream out, final OutputStream err, final String[] args) throws IOException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
try {
ctxOut.setDelegatee(out);
ctxErr.setDelegatee(err);
final ErrorManager errors = context.getErrorManager();
- final ScriptObject global = context.createGlobal();
+ final Global global = context.createGlobal();
Context.setGlobal(global);
// For each file on the command line.