Bläddra i källkod

Merge remote-tracking branch 'origin/development' into remove_err_depth

Rudy Ges 2 månader sedan
förälder
incheckning
71c3ce265f
100 ändrade filer med 1301 tillägg och 485 borttagningar
  1. 2 1
      .github/workflows/main.yml
  2. 2 1
      .github/workflows/target.yml
  3. 1 1
      Makefile
  4. 6 0
      WinSetup.ps1
  5. 20 0
      extra/CHANGES.txt
  6. 4 2
      extra/ImportAll.hx
  7. 2 1
      extra/github-actions/install-ocaml-windows.yml
  8. 1 1
      extra/haxelib_src
  9. 2 0
      libs/extc/extc.ml
  10. 25 2
      libs/extc/extc_stubs.c
  11. 3 1
      libs/objsize/objsize.ml
  12. 41 0
      src-json/define.json
  13. 4 4
      src/codegen/codegen.ml
  14. 1 1
      src/codegen/genxml.ml
  15. 11 7
      src/compiler/compilationCache.ml
  16. 2 2
      src/compiler/compiler.ml
  17. 1 0
      src/compiler/hxb/hxbReader.ml
  18. 1 0
      src/compiler/hxb/hxbWriter.ml
  19. 2 2
      src/compiler/server.ml
  20. 1 0
      src/compiler/serverCompilationContext.ml
  21. 5 1
      src/compiler/serverMessage.ml
  22. 40 6
      src/context/abstractCast.ml
  23. 119 37
      src/context/common.ml
  24. 1 1
      src/context/commonCache.ml
  25. 5 7
      src/context/display/deprecationCheck.ml
  26. 7 3
      src/context/display/diagnosticsPrinter.ml
  27. 31 4
      src/context/display/displayFields.ml
  28. 3 0
      src/context/display/displayMemory.ml
  29. 1 1
      src/context/display/findReferences.ml
  30. 0 1
      src/context/display/statistics.ml
  31. 17 0
      src/context/dotGraph.ml
  32. 32 14
      src/context/parallel.ml
  33. 1 1
      src/context/safeCom.ml
  34. 20 6
      src/context/typecore.ml
  35. 4 7
      src/core/define.ml
  36. 0 11
      src/core/display/completionItem.ml
  37. 12 0
      src/core/ds/threadSafeHashtbl.ml
  38. 2 1
      src/core/json/genjson.ml
  39. 1 1
      src/core/tOther.ml
  40. 1 0
      src/core/tPrinting.ml
  41. 11 1
      src/core/tType.ml
  42. 4 3
      src/core/tUnification.ml
  43. 10 0
      src/core/texpr.ml
  44. 1 9
      src/core/warning.ml
  45. 2 1
      src/filters/exception/saveStacks.ml
  46. 8 8
      src/filters/filters.ml
  47. 0 1
      src/filters/filtersCommon.ml
  48. 28 52
      src/filters/safe/capturedVars.ml
  49. 8 8
      src/generators/cpp/cppRetyper.ml
  50. 1 1
      src/generators/cpp/gen/cppCppia.ml
  51. 13 13
      src/generators/cpp/gen/cppGenClassImplementation.ml
  52. 4 4
      src/generators/flashProps.ml
  53. 2 2
      src/generators/gctx.ml
  54. 14 15
      src/generators/genhl.ml
  55. 1 1
      src/generators/genjvm.ml
  56. 8 0
      src/generators/genlua.ml
  57. 2 0
      src/generators/genphp7.ml
  58. 2 2
      src/generators/genpy.ml
  59. 4 4
      src/generators/genswf9.ml
  60. 87 0
      src/macro/eval/evalAtomic.ml
  61. 18 18
      src/macro/eval/evalEmitter.ml
  62. 24 1
      src/macro/eval/evalExceptions.ml
  63. 4 0
      src/macro/eval/evalHash.ml
  64. 3 3
      src/macro/eval/evalStackTrace.ml
  65. 7 1
      src/macro/eval/evalStdLib.ml
  66. 11 1
      src/macro/eval/evalValue.ml
  67. 10 1
      src/macro/macroApi.ml
  68. 7 13
      src/optimization/analyzer.ml
  69. 13 4
      src/optimization/analyzerTexpr.ml
  70. 10 4
      src/optimization/dce.ml
  71. 1 1
      src/optimization/inline.ml
  72. 20 17
      src/optimization/inlineConstructors.ml
  73. 20 2
      src/prebuild.ml
  74. 1 0
      src/syntax/grammar.ml
  75. 4 13
      src/syntax/lexer.ml
  76. 0 1
      src/syntax/parserConfig.ml
  77. 2 2
      src/typing/callUnification.ml
  78. 1 1
      src/typing/fieldAccess.ml
  79. 34 7
      src/typing/fields.ml
  80. 7 1
      src/typing/generic.ml
  81. 11 12
      src/typing/macroContext.ml
  82. 164 53
      src/typing/nullSafety.ml
  83. 8 5
      src/typing/operators.ml
  84. 3 0
      src/typing/typeload.ml
  85. 12 5
      src/typing/typeloadCheck.ml
  86. 24 9
      src/typing/typeloadFields.ml
  87. 0 1
      src/typing/typeloadModule.ml
  88. 18 11
      src/typing/typer.ml
  89. 51 1
      src/typing/typerEntry.ml
  90. 8 1
      std/cpp/_std/haxe/Exception.hx
  91. 47 0
      std/cpp/_std/haxe/atomic/AtomicBool.hx
  92. 43 11
      std/cpp/_std/haxe/atomic/AtomicInt.hx
  93. 2 0
      std/eval/_std/Sys.hx
  94. 16 1
      std/eval/_std/haxe/Exception.hx
  95. 5 1
      std/flash/_std/haxe/Exception.hx
  96. 1 1
      std/haxe/CallStack.hx
  97. 2 1
      std/haxe/Exception.hx
  98. 36 1
      std/haxe/Timer.hx
  99. 8 27
      std/haxe/atomic/AtomicBool.hx
  100. 1 0
      std/haxe/display/JsonModuleTypes.hx

+ 2 - 1
.github/workflows/main.yml

@@ -53,7 +53,8 @@ jobs:
         run: neko -version 2>&1
 
       - name: Setup ocaml
-        uses: ocaml/setup-ocaml@v3
+      # Lock to 3.2.19 to work around an issue with 32-bit libraries getting installed
+        uses: ocaml/setup-ocaml@3d85bf33a66e089149cd1e9c75da7b9cb6d9d3a7
         with:
           ocaml-compiler: ${{ env.OCAML_VERSION }}
           opam-local-packages: |

+ 2 - 1
.github/workflows/target.yml

@@ -8,12 +8,13 @@ on:
       - edited
 jobs:
   check-branches:
+    if: github.repository == 'HaxeFoundation/haxe'
     runs-on: ubuntu-latest
     steps:
       - name: Check branches
         run: |
           if [ ${{ github.base_ref }} != "development" ]; then
-            echo "Merge requests should target `development`."
+            echo "Merge requests should target development."
             exit 1
           fi
 

+ 1 - 1
Makefile

@@ -59,7 +59,7 @@ PACKAGE_FILE_NAME=haxe_$(COMMIT_DATE)_$(COMMIT_SHA)
 HAXE_VERSION=$(shell $(CURDIR)/$(HAXE_OUTPUT) -version 2>&1 | awk '{print $$1;}')
 HAXE_VERSION_SHORT=$(shell echo "$(HAXE_VERSION)" | grep -oE "^[0-9]+\.[0-9]+\.[0-9]+")
 
-NEKO_VERSION=2.4.0-rc.1
+NEKO_VERSION=2.4.1
 NEKO_MAJOR_VERSION=$(shell echo "$(NEKO_VERSION)" | grep -oE "^[0-9]+")
 NEKO_VERSION_TAG=v$(shell echo "$(NEKO_VERSION)" | sed "s/\./-/g")
 

+ 6 - 0
WinSetup.ps1

@@ -3,6 +3,12 @@
 # - install Neko
 # - checkout haxe git
 # - run from command "powershell -noexit -ExecutionPolicy Bypass -File .\WinSetup.ps1"
+#
+# Troubleshooting :
+# - make error #127 :
+#	  - cause : you have a local cygwin instance that takes precedence over the opam one.
+#     - solution : adjust your environment variables so opam takes precedence
+#
 
 function Cmd-Path($file) {
 	try { Split-Path -Parent (Get-Command "$file.exe" -ErrorAction Stop).Source } catch { "" }

+ 20 - 0
extra/CHANGES.txt

@@ -1,3 +1,23 @@
+2025-05-09 4.3.7
+
+	General improvements:
+
+	all : update bundled haxelib version to 4.1.1
+	all : update bundled neko version to 2.4.1 (#12183)
+	all : use -w rules instead of defines to configure warnings (#11826, #12013)
+
+	Bugfixes:
+
+	all : fix compiler hanging issue (#11820)
+	all : local statics fixes (#11803, #11849)
+	all : fix for inline constructor bug triggering "Unbound variable" (#12169)
+	all : check caught error position when recovering from match typing failure (#12098)
+	macro : local statics vs ExprTools.map (#12030)
+	eval : https fixes (mbedtls update) (#11646)
+	eval : ssl cert verification failures on windows (#11838)
+	hl/c : fix comparison of HArray,HArray and HBytes,HBytes (#11610)
+	cppia : generate scriptable functions for overriden functions (#11773)
+
 2024-08-07 4.3.6
 
 	Bugfixes:

+ 4 - 2
extra/ImportAll.hx

@@ -78,8 +78,10 @@ class ImportAll {
 				if( !sys.FileSystem.exists(p) || !sys.FileSystem.isDirectory(p) )
 					continue;
 				for( file in sys.FileSystem.readDirectory(p) ) {
-					if( file == ".svn" || file == "_std" )
-						continue;
+					switch (file) {
+						case ".svn" | "_std" | "import.hx":
+							continue;
+					}
 					var full = (pack == "") ? file : pack + "." + file;
 					if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) {
 						var cl = full.substr(0, full.length - 3);

+ 2 - 1
extra/github-actions/install-ocaml-windows.yml

@@ -1,5 +1,6 @@
 - name: Setup ocaml
-  uses: ocaml/setup-ocaml@v3
+# Lock to 3.2.19 to work around an issue with 32-bit libraries getting installed
+  uses: ocaml/setup-ocaml@3d85bf33a66e089149cd1e9c75da7b9cb6d9d3a7
   with:
     ocaml-compiler: ${{ env.OCAML_VERSION }}
     opam-local-packages: |

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit 5a836287828fdaeb6aa91695a5eb399cee0f6640
+Subproject commit 436bd844f90c61100b13a108912c1f7e918aead3

+ 2 - 0
libs/extc/extc.ml

@@ -51,6 +51,8 @@ external zlib_crc32 : bytes -> int -> int32 = "zlib_crc32"
 
 external time : unit -> float = "sys_time"
 
+external timestamp_ms : unit -> int64 = "sys_timestamp_ms"
+
 external getch : bool -> int = "sys_getch"
 
 external filetime : string -> float = "sys_filetime"

+ 25 - 2
libs/extc/extc_stubs.c

@@ -487,11 +487,14 @@ CAMLprim value get_real_path( value path ) {
 #define TimeSpecToSeconds(ts) (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0
 #endif
 
+#ifdef WIN32
+static LARGE_INTEGER freq;
+static int freq_init = -1;
+#endif
+
 CAMLprim value sys_time() {
 #ifdef _WIN32
 #define EPOCH_DIFF	(134774*24*60*60.0)
-	static LARGE_INTEGER freq;
-	static int freq_init = -1;
 	LARGE_INTEGER counter;
 	if( freq_init == -1 )
 		freq_init = QueryPerformanceFrequency(&freq);
@@ -533,6 +536,26 @@ CAMLprim value sys_time() {
 #endif
 }
 
+CAMLprim value sys_timestamp_ms() {
+#ifdef _WIN32
+	if (-1 == freq_init) {
+		freq_init = QueryPerformanceFrequency(&freq);
+	}
+
+	LARGE_INTEGER time;
+	QueryPerformanceCounter(&time);
+
+	return caml_copy_int64(time.QuadPart * 1000LL / freq.QuadPart);
+#else
+	struct timespec ts;
+	if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
+		caml_failwith("Failed to get time from the monotonic clock");
+	}
+
+	return caml_copy_int64(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000));
+#endif
+}
+
 CAMLprim value sys_getch( value b ) {
 #	ifdef _WIN32
 	return Val_int( Bool_val(b)?getche():getch() );

+ 3 - 1
libs/objsize/objsize.ml

@@ -11,7 +11,9 @@ type info =
 
 external internal_objsize : Obj.t -> Obj.t list -> Obj.t list -> info = "ml_objsize"
 
-let objsize obj exclude reach = internal_objsize (Obj.repr obj) exclude reach
+let objsize obj (exclude:Obj.t list) (reach:Obj.t list) =
+  (* internal_objsize (Obj.repr obj) exclude reach *)
+  {data = (Obj.reachable_words (Obj.repr obj)); headers = 0; depth = 0; reached = false}
 
 let size_with_headers i = (Sys.word_size/8) * (i.data + i.headers)
 

+ 41 - 0
src-json/define.json

@@ -20,6 +20,7 @@
 		"name": "AnalyzerTimes",
 		"define": "times.analyzer",
 		"deprecatedDefine": "analyzer-times",
+		"signatureNeutral": true,
 		"doc": "Record detailed timers for the analyzer",
 		"params": ["level: 0 | 1 | 2"]
 	},
@@ -60,6 +61,7 @@
 	{
 		"name": "DceDebug",
 		"define": "dce-debug",
+		"signatureNeutral": true,
 		"doc": "Show DCE log.",
 		"links": ["https://haxe.org/manual/cr-dce.html"]
 	},
@@ -71,13 +73,21 @@
 	{
 		"name": "DisableHxbCache",
 		"define": "disable-hxb-cache",
+		"signatureNeutral": true,
 		"doc": "Use in-memory cache instead of hxb powered cache."
 	},
 	{
 		"name": "DisableHxbOptimizations",
 		"define": "disable-hxb-optimizations",
+		"signatureNeutral": true,
 		"doc": "Disable shortcuts used by hxb cache to speed up display requests."
 	},
+	{
+		"name": "EnableParallelism",
+		"define": "enable-parallelism",
+		"signatureNeutral": true,
+		"doc": "Enable experimental uses of parallelism in the compiler."
+	},
 	{
 		"name": "DisableUnicodeStrings",
 		"define": "disable-unicode-strings",
@@ -87,14 +97,23 @@
 	{
 		"name": "Display",
 		"define": "display",
+		"signatureNeutral": true,
 		"doc": "Activated during completion.",
 		"links": ["https://haxe.org/manual/cr-completion.html"]
 	},
 	{
 		"name": "DisplayStdin",
 		"define": "display-stdin",
+		"signatureNeutral": true,
 		"doc": "Read the contents of a file specified in `--display` from standard input."
 	},
+	{
+		"name": "DisplayDetails",
+		"define": "display-details",
+		"signatureNeutral": true,
+		"doc": "Not used anymore, but still sent by vshaxe.",
+		"deprecated": "This flag is no longer supported in Haxe 5"
+	},
 	{
 		"name": "DllExport",
 		"define": "dll-export",
@@ -109,12 +128,14 @@
 	{
 		"name": "Dump",
 		"define": "dump",
+		"signatureNeutral": true,
 		"doc": "Dump typed AST in dump subdirectory using specified mode or non-prettified default.",
 		"params": ["mode: pretty | record | position | legacy"]
 	},
 	{
 		"name": "DumpStage",
 		"define": "dump.stage",
+		"signatureNeutral": true,
 		"doc": "The compiler stage after which to generate the dump",
 		"params": ["stage: typing | casting | inlining | analyzing | dce"],
 		"default": "dce"
@@ -122,6 +143,7 @@
 	{
 		"name": "DumpPath",
 		"define": "dump-path",
+		"signatureNeutral": true,
 		"doc": "Path to generate dumps to (default: \"dump\").",
 		"default": "dump",
 		"params": ["path"]
@@ -129,11 +151,13 @@
 	{
 		"name": "DumpDependencies",
 		"define": "dump-dependencies",
+		"signatureNeutral": true,
 		"doc": "Dump the classes dependencies in a dump subdirectory."
 	},
 	{
 		"name": "DumpIgnoreVarIds",
 		"define": "dump-ignore-var-ids",
+		"signatureNeutral": true,
 		"doc": "Remove variable IDs from non-pretty dumps (helps with diff).",
 		"default": "1"
 	},
@@ -181,18 +205,21 @@
 		"name": "EvalTimes",
 		"define": "times.eval",
 		"deprecatedDefine": "eval-times",
+		"signatureNeutral": true,
 		"doc": "Record per-method execution times in macro/interp mode. Implies eval-stack.",
 		"platforms": ["eval"]
 	},
 	{
 		"name": "FailFast",
 		"define": "fail-fast",
+		"signatureNeutral": true,
 		"doc": "Abort compilation when first error occurs."
 	},
 	{
 		"name": "FilterTimes",
 		"define": "times.filter",
 		"deprecatedDefine": "filter-times",
+		"signatureNeutral": true,
 		"doc": "Record per-filter execution times upon --times."
 	},
 	{
@@ -311,8 +338,15 @@
 		"name": "HxbTimes",
 		"define": "times.hxb",
 		"deprecatedDefine": "hxb-times",
+		"signatureNeutral": true,
 		"doc": "Display hxb timing when used with `--times`."
 	},
+	{
+		"name": "HxbStats",
+		"define": "hxb.stats",
+		"signatureNeutral": true,
+		"doc": "Display some hxb related stats (only with compilation server)."
+	},
 	{
 		"name": "HxcppApiLevel",
 		"define": "hxcpp-api-level",
@@ -550,6 +584,7 @@
 		"name": "MacroTimes",
 		"define": "times.macro",
 		"deprecatedDefine": "macro-times",
+		"signatureNeutral": true,
 		"doc": "Display per-macro timing when used with `--times`."
 	},
 	{
@@ -582,6 +617,7 @@
 	{
 		"name": "NoCompilation",
 		"define": "no-compilation",
+		"signatureNeutral": true,
 		"doc": "Disable final compilation.",
 		"platforms": ["cpp", "hl"]
 	},
@@ -843,6 +879,7 @@
 	{
 		"name": "MessageReporting",
 		"define": "message.reporting",
+		"signatureNeutral": true,
 		"doc": "Select message reporting mode for compiler output. (default: pretty)",
 		"default": "pretty",
 		"params": ["mode: classic | pretty | indent"]
@@ -850,21 +887,25 @@
 	{
 		"name": "MessageNoColor",
 		"define": "message.no-color",
+		"signatureNeutral": true,
 		"doc": "Disable ANSI color codes in message reporting."
 	},
 	{
 		"name": "MessageAbsolutePositions",
 		"define": "message.absolute-positions",
+		"signatureNeutral": true,
 		"doc": "Use absolute character positions instead of line/columns for message reporting."
 	},
 	{
 		"name": "MessageLogFile",
 		"define": "message.log-file",
+		"signatureNeutral": true,
 		"doc": "Path to a text file to write message reporting to, in addition to regular output."
 	},
 	{
 		"name": "MessageLogFormat",
 		"define": "message.log-format",
+		"signatureNeutral": true,
 		"doc": "Select message reporting mode for message log file. (default: indent)",
 		"default": "indent",
 		"params": ["format: classic | pretty | indent"]

+ 4 - 4
src/codegen/codegen.ml

@@ -28,8 +28,8 @@ open Extlib_leftovers
 let rec has_properties c =
 	List.exists (fun f ->
 		match f.cf_kind with
-		| Var { v_read = AccCall } -> true
-		| Var { v_write = AccCall } -> true
+		| Var { v_read = AccCall | AccPrivateCall } -> true
+		| Var { v_write = AccCall | AccPrivateCall } -> true
 		| _ when Meta.has Meta.Accessor f.cf_meta -> true
 		| _ -> false
 	) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false)
@@ -40,10 +40,10 @@ let get_properties fields =
 			(f.cf_name, f.cf_name) :: acc
 		else
 			let acc = (match f.cf_kind with
-			| Var { v_read = AccCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc
+			| Var { v_read = AccCall | AccPrivateCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc
 			| _ -> acc) in
 			match f.cf_kind with
-			| Var { v_write = AccCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc
+			| Var { v_write = AccCall | AccPrivateCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc
 			| _ -> acc
 	) [] fields
 

+ 1 - 1
src/codegen/genxml.ml

@@ -135,7 +135,7 @@ and gen_field att f =
 		match acc with
 		| AccNormal | AccRequire _ | AccCtor -> att
 		| AccNo | AccNever -> (name, "null") :: att
-		| AccCall -> (name,"accessor") :: att
+		| AccCall | AccPrivateCall -> (name,"accessor") :: att
 		| AccInline -> (name,"inline") :: att
 	in
 	let att = (match f.cf_expr with None -> att | Some e -> ("line",string_of_int (Lexer.get_error_line e.epos)) :: att) in

+ 11 - 7
src/compiler/compilationCache.ml

@@ -36,6 +36,7 @@ class context_cache (index : int) (sign : Digest.t) = object(self)
 	val modules : (path,module_def) Hashtbl.t = Hashtbl.create 0
 	val binary_cache : (path,HxbData.module_cache) Hashtbl.t = Hashtbl.create 0
 	val tmp_binary_cache : (path,HxbData.module_cache) Hashtbl.t = Hashtbl.create 0
+	val get_hxb_module_mutex = Mutex.create ()
 	val removed_files = Hashtbl.create 0
 	val mutable json = JNull
 	val mutable initialized = false
@@ -68,13 +69,16 @@ class context_cache (index : int) (sign : Digest.t) = object(self)
 		Hashtbl.find_opt modules path
 
 	method get_hxb_module path =
-		try Hashtbl.find tmp_binary_cache path
-		with Not_found ->
-			let mc = Hashtbl.find binary_cache path in
-			let m_extra = { mc.mc_extra with m_deps = mc.mc_extra.m_deps } in
-			let mc = { mc with mc_extra = m_extra } in
-			Hashtbl.add tmp_binary_cache path mc;
-			mc
+		Mutex.protect get_hxb_module_mutex (fun () ->
+			try
+				Hashtbl.find tmp_binary_cache path
+			with Not_found ->
+				let mc = Hashtbl.find binary_cache path in
+				let m_extra = { mc.mc_extra with m_deps = mc.mc_extra.m_deps } in
+				let mc = { mc with mc_extra = m_extra } in
+				Hashtbl.add tmp_binary_cache path mc;
+				mc
+		)
 
 	method find_module_extra path =
 		try (Hashtbl.find modules path).m_extra

+ 2 - 2
src/compiler/compiler.ml

@@ -270,6 +270,7 @@ module Setup = struct
 end
 
 let check_defines com =
+	if defined com Define.EnableParallelism then Parallel.enable := true;
 	PMap.iter (fun k v ->
 		try
 			let reason = Hashtbl.find Define.deprecation_lut k in
@@ -297,6 +298,7 @@ let do_type ctx mctx actx display_file_dot_path =
 		Some (MacroContext.call_init_macro ctx.com mctx path)
 	) mctx (List.rev actx.config_macros) in
 	enter_stage com CInitMacrosDone;
+	check_defines ctx.com;
 	update_platform_config com; (* make sure to adapt all flags changes defined during init macros *)
 	ServerMessage.compiler_stage com;
 
@@ -304,7 +306,6 @@ let do_type ctx mctx actx display_file_dot_path =
 	Setup.init_native_libs com actx.native_libs;
 	let tctx = Setup.create_typer_context ctx macros in
 	let display_file_dot_path = DisplayProcessing.maybe_load_display_file_before_typing tctx display_file_dot_path in
-	check_defines ctx.com;
 	DumpConfig.update_from_defines com.dump_config com.defines;
 	CommonCache.lock_signature com "after_init_macros";
 	Option.may (fun mctx -> MacroContext.finalize_macro_api tctx mctx) mctx;
@@ -347,7 +348,6 @@ let finalize_typing ctx tctx =
 
 let filter ctx tctx ectx before_destruction =
 	Timer.time ctx.timer_ctx ["filters"] (fun () ->
-		DeprecationCheck.run ctx.com;
 		run_or_diagnose ctx (fun () -> Filters.run tctx ectx ctx.com.main.main_expr before_destruction)
 	) ()
 

+ 1 - 0
src/compiler/hxb/hxbReader.ml

@@ -993,6 +993,7 @@ class hxb_reader
 					let s = self#read_string in
 					let so = self#read_option (fun () -> self#read_string) in
 					AccRequire(s,so)
+				| 7 -> AccPrivateCall
 				| i ->
 					error (Printf.sprintf "Bad accessor kind: %i" i)
 			in

+ 1 - 0
src/compiler/hxb/hxbWriter.ml

@@ -1710,6 +1710,7 @@ module HxbWriter = struct
 					Chunk.write_u8 writer.chunk 6;
 					Chunk.write_string writer.chunk s;
 					Chunk.write_option writer.chunk so (Chunk.write_string writer.chunk)
+				| AccPrivateCall -> Chunk.write_u8 writer.chunk 7
 			in
 			f r;
 			f w

+ 2 - 2
src/compiler/server.ml

@@ -481,8 +481,8 @@ let handle_cache_bound_objects com cbol =
 			Hashtbl.replace com.resources name data
 		| IncludeFile(file,position) ->
 			com.include_files <- (file,position) :: com.include_files
-		| Warning(w,msg,p) ->
-			com.warning w [] msg p
+		| Warning(w,options,msg,p) ->
+			com.warning w options msg p
 	) cbol
 
 (* Adds module [m] and all its dependencies (recursively) from the cache to the current compilation

+ 1 - 0
src/compiler/serverCompilationContext.ml

@@ -44,6 +44,7 @@ let reset sctx =
 	Hashtbl.clear sctx.changed_directories;
 	sctx.was_compilation <- false;
 	Parser.reset_state();
+	Parallel.enable := false;
 	Hashtbl.clear DeprecationCheck.warned_positions;
 	stats.s_files_parsed := 0;
 	stats.s_classes_built := 0;

+ 5 - 1
src/compiler/serverMessage.ml

@@ -24,6 +24,7 @@ type server_message_options = {
 	mutable print_signature : bool;
 	mutable print_display_position : bool;
 	mutable print_stats : bool;
+	mutable print_gc_stats : bool;
 	mutable print_message : bool;
 	mutable print_socket_message : bool;
 	mutable print_uncaught_error : bool;
@@ -51,6 +52,7 @@ let config = {
 	print_signature = false;
 	print_display_position = false;
 	print_stats = false;
+	print_gc_stats = false;
 	print_message = false;
 	print_socket_message = false;
 	print_uncaught_error = false;
@@ -143,7 +145,7 @@ let message s =
 	if config.print_message then print_endline ("> " ^ s)
 
 let gc_stats time stats_before did_compact space_overhead =
-	if config.print_stats then begin
+	if config.print_stats || config.print_gc_stats then begin
 		let stats = Gc.quick_stat() in
 		print_endline (Printf.sprintf "GC %s done in %.2fs with space_overhead = %i\n\tbefore: %s\n\tafter: %s"
 			(if did_compact then "compaction" else "collection")
@@ -180,6 +182,7 @@ let enable_all () =
 	config.print_signature <- true;
 	config.print_display_position <- true;
 	config.print_stats <- true;
+	config.print_gc_stats <- true;
 	config.print_message <- true;
 	config.print_socket_message <- true;
 	config.print_uncaught_error <- true;
@@ -205,6 +208,7 @@ let set_by_name name value = match name with
 	| "signature" -> config.print_signature <- value;
 	| "displayPosition" -> config.print_display_position <- value;
 	| "stats" -> config.print_stats <- value;
+	| "gcStats" -> config.print_gc_stats <- value;
 	| "message" -> config.print_message <- value;
 	| "socketMessage" -> config.print_socket_message <- value;
 	| "uncaughtError" -> config.print_uncaught_error <- value;

+ 40 - 6
src/context/abstractCast.ml

@@ -200,13 +200,45 @@ let find_array_write_access ctx a tl e1 e2 p =
 		let s_type = s_type (print_context()) in
 		raise_typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts arguments of %s and %s" (s_type (TAbstract(a,tl))) (s_type e1.etype) (s_type e2.etype)) p
 
+(* TODO: This duplicates pretty much all the code from unifies_to_field. The only reason for that is
+   that we want the monos so we can apply them to the type. Surely we can design our data better here... *)
+let find_to_field uctx b ab tl =
+	let a = TAbstract(ab,tl) in
+	let check t cf = match follow cf.cf_type with
+		| TFun((_,_,ta) :: _,_) ->
+			let map = apply_params ab.a_params tl in
+			let monos = Monomorph.spawn_constrained_monos map cf.cf_params in
+			let map t = map (apply_params cf.cf_params monos t) in
+			let uctx = get_abstract_context uctx a b ab in
+			let unify_func = get_abstract_unify_func uctx EqStrict in
+			let athis = map ab.a_this in
+			(* we cannot allow implicit casts when the this type is not completely known yet *)
+			if Meta.has Meta.MultiType ab.a_meta && has_mono athis then raise (Unify_error []);
+			with_variance uctx (type_eq_custom {uctx with equality_kind = EqStrict}) athis (map ta);
+			unify_func (map t) b;
+			t,cf,monos
+		| _ ->
+			die "" __LOC__
+	in
+	let rec loop cfl = match cfl with
+		| [] ->
+			raise Not_found
+		| (t,cf) :: cfl ->
+			begin try
+				check t cf
+			with Unify_error _ ->
+				loop cfl
+			end
+	in
+	loop ab.a_to_field
+
 let find_multitype_specialization' platform a pl p =
 	let uctx = default_unification_context () in
 	let m = mk_mono() in
 	let tl,definitive_types = Abstract.find_multitype_params a pl in
-	let _,cf =
+	let _,cf,field_monos =
 		try
-			let t = Abstract.find_to uctx m a tl in
+			let t = find_to_field uctx m a tl in
 			if List.exists (fun t -> has_mono t) definitive_types then begin
 				let at = apply_params a.a_params pl a.a_this in
 				let st = s_type (print_context()) at in
@@ -221,10 +253,10 @@ let find_multitype_specialization' platform a pl p =
 			else
 				raise_typing_error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
 	in
-	cf,follow m,tl
+	cf,field_monos,follow m,tl
 
 let find_multitype_specialization platform a pl p =
-	let cf,m,_ = find_multitype_specialization' platform a pl p in
+	let cf,field_monos,m,_ = find_multitype_specialization' platform a pl p in
 	(cf,m)
 
 let handle_abstract_casts (scom : SafeCom.t) e =
@@ -238,8 +270,10 @@ let handle_abstract_casts (scom : SafeCom.t) e =
 				| _ -> raise_typing_error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos
 			end else begin
 				(* a TNew of an abstract implementation is only generated if it is a multi type abstract *)
-				let cf,m,pl = find_multitype_specialization' scom.platform a pl e.epos in
-				let e = ExceptionFunctions.make_static_call scom c cf ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el)  m e.epos in
+				let cf,field_monos,m,pl = find_multitype_specialization' scom.platform a pl e.epos in
+				let e_this = Texpr.Builder.make_static_this c e.epos in
+				let ef = mk (TField(e_this,FStatic(c,cf))) (apply_params cf.cf_params field_monos cf.cf_type) e.epos in
+				let e = ExceptionFunctions.make_call scom ef ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el) m e.epos in
 				{e with etype = m}
 			end
 		| TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) ->

+ 119 - 37
src/context/common.ml

@@ -22,7 +22,6 @@ open Globals
 open Lookup
 open Define
 open NativeLibraries
-open Warning
 
 type package_rule =
 	| Forbidden
@@ -234,6 +233,34 @@ type parser_state = {
 	special_identifier_files : (Path.UniqueKey.t,string) ThreadSafeHashtbl.t;
 }
 
+module LocalWrapper = struct
+	type t = <
+		captured_type : TType.t -> TType.t;
+		mk_init : tvar -> tvar -> pos -> texpr;
+		mk_ref : tvar -> texpr option -> pos -> texpr;
+		mk_ref_access : texpr -> tvar -> texpr
+	>
+
+	let null_wrapper = object
+		method captured_type =
+			(fun t -> t)
+
+		method mk_ref v ve p =
+			let ev = Texpr.Builder.make_local v p in
+			match ve with
+			| None ->
+				ev
+			| Some e ->
+				Texpr.Builder.binop OpAssign ev e ev.etype p
+
+		method mk_ref_access e v =
+			e
+
+		method mk_init av v p =
+			mk (TVar (av,Some (mk (TLocal v) v.v_type p))) t_dynamic p
+	end
+end
+
 type context = {
 	compilation_step : int;
 	mutable stage : compiler_stage;
@@ -265,7 +292,7 @@ type context = {
 	mutable error_ext : Error.error -> unit;
 	mutable info : ?depth:int -> ?from_macro:bool -> string -> pos -> unit;
 	mutable warning : Gctx.warning_function;
-	mutable warning_options : Warning.warning_option list list;
+	mutable warning_options : warning_option list list;
 	mutable get_messages : unit -> compiler_message list;
 	mutable filter_messages : (compiler_message -> bool) -> unit;
 	mutable run_command : string -> int;
@@ -277,6 +304,7 @@ type context = {
 	mutable user_defines : (string, Define.user_define) Hashtbl.t;
 	mutable user_metas : (string, Meta.user_meta) Hashtbl.t;
 	mutable get_macros : unit -> context option;
+	mutable local_wrapper : LocalWrapper.t;
 	(* typing state *)
 	mutable std : tclass;
 	mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
@@ -307,8 +335,6 @@ type context = {
 	mutable include_files : (string * string) list;
 	mutable native_libs : native_libraries;
 	mutable hxb_libs : abstract_hxb_lib list;
-	mutable net_std : string list;
-	net_path_map : (path,string list * string list * string) Hashtbl.t;
 	mutable js_gen : (unit -> unit) option;
 	(* misc *)
 	mutable basic : basic_types;
@@ -354,7 +380,7 @@ let ignore_error com =
 	b
 
 let module_warning com m w options msg p =
-	if com.display.dms_full_typing then DynArray.add m.m_extra.m_cache_bound_objects (Warning(w,msg,p));
+	if com.display.dms_full_typing then DynArray.add m.m_extra.m_cache_bound_objects (Warning(w,options,msg,p));
 	com.warning w options msg p
 
 (* Defines *)
@@ -679,7 +705,8 @@ let get_config com =
 			pf_capture_policy = CPWrapRef;
 			pf_exceptions = { default_config.pf_exceptions with
 				ec_avoid_wrapping = false
-			}
+			};
+			pf_supports_atomics = true;
 		}
 
 let memory_marker = [|Unix.time()|]
@@ -732,10 +759,8 @@ let create timer_ctx compilation_step cs version args display_mode =
 		fake_modules = Hashtbl.create 0;
 		flash_version = 10.;
 		resources = Hashtbl.create 0;
-		net_std = [];
 		native_libs = create_native_libs();
 		hxb_libs = [];
-		net_path_map = Hashtbl.create 0;
 		neko_lib_paths = [];
 		include_files = [];
 		js_gen = None;
@@ -744,6 +769,7 @@ let create timer_ctx compilation_step cs version args display_mode =
 		user_defines = Hashtbl.create 0;
 		user_metas = Hashtbl.create 0;
 		get_macros = (fun() -> None);
+		local_wrapper = LocalWrapper.null_wrapper;
 		info = (fun ?depth ?from_macro _ _ -> die "" __LOC__);
 		warning = (fun ?depth ?from_macro _ _ _ -> die "" __LOC__);
 		warning_options = [List.map (fun w -> {wo_warning = w;wo_mode = WMDisable}) WarningList.disabled_warnings];
@@ -805,47 +831,103 @@ let log com str =
 	if com.verbose then com.print (str ^ "\n")
 
 let clone com is_macro_context =
-	let t = com.basic in
-	{ com with
+	{
+		(* keeps *)
+		compilation_step = com.compilation_step;
+		cs = com.cs;
+		timer_ctx = com.timer_ctx;
+		version = com.version;
+		args = com.args;
+		shared = com.shared;
+		debug = com.debug;
+		display = com.display;
+		verbose = com.verbose;
+		foptimize = com.foptimize;
+		doinline = com.doinline;
+		platform = com.platform;
+		config = com.config;
+		print = com.print;
+		run_command = com.run_command;
+		run_command_args = com.run_command_args;
+		package_rules = com.package_rules;
+		file = com.file;
+		global_metadata = com.global_metadata;
+		flash_version = com.flash_version;
+		resources = com.resources;
+		native_libs = com.native_libs;
+		hxb_libs = com.hxb_libs;
+		neko_lib_paths = com.neko_lib_paths;
+		include_files = com.include_files;
+		js_gen = com.js_gen;
+		defines = {
+			values = com.defines.values;
+			defines_signature = com.defines.defines_signature;
+		};
+		user_defines = com.user_defines;
+		user_metas = com.user_metas;
+		get_macros = com.get_macros;
+		info = com.info;
+		warning = com.warning;
+		warning_options = com.warning_options;
+		error = com.error;
+		error_ext = com.error_ext;
+		get_messages = com.get_messages;
+		filter_messages = com.filter_messages;
+		pass_debug_messages = com.pass_debug_messages;
+		file_keys = com.file_keys;
+		stored_typed_exprs = com.stored_typed_exprs;
+		cached_macros = com.cached_macros;
+		memory_marker = com.memory_marker;
+		json_out = com.json_out;
+		has_error = com.has_error;
+		report_mode = com.report_mode;
+		hxb_writer_config = com.hxb_writer_config;
+		parser_state = com.parser_state;
+		dump_config = com.dump_config;
+		file_contents = com.file_contents;
+		(* reinits *)
 		cache = None;
 		stage = CCreated;
-		basic = { t with
-			tvoid = mk_mono();
-			tany = mk_mono();
-			tint = mk_mono();
-			tfloat = mk_mono();
-			tbool = mk_mono();
-			tstring = mk_mono();
+		display_information = {
+			unresolved_identifiers = [];
+			display_module_has_macro_defines = false;
+			module_diagnostics = [];
 		};
+		features = Hashtbl.create 0;
+		empty_class_path = new ClassPath.directory_class_path "" User;
+		class_paths = new ClassPaths.class_paths;
 		main = {
 			main_path = None;
 			main_file = None;
 			main_expr = None;
 		};
-		features = Hashtbl.create 0;
+		types = [];
 		callbacks = new compiler_callbacks;
-		display_information = {
-			unresolved_identifiers = [];
-			display_module_has_macro_defines = false;
-			module_diagnostics = [];
-		};
-		defines = {
-			values = com.defines.values;
-			defines_signature = com.defines.defines_signature;
-		};
-		native_libs = create_native_libs();
-		is_macro_context = is_macro_context;
-		parser_cache = new hashtbl_lookup;
-		module_to_file = new hashtbl_lookup;
-		overload_cache = new hashtbl_lookup;
+		modules = [];
 		module_lut = new module_lut;
+		module_nonexistent_lut = new hashtbl_lookup;
 		fake_modules = Hashtbl.create 0;
-		hxb_reader_api = None;
-		hxb_reader_stats = HxbReader.create_hxb_reader_stats ();
+		load_extern_type = []; (* ! *)
+		basic = {
+			tvoid = mk_mono();
+			tany = mk_mono();
+			tint = mk_mono();
+			tfloat = mk_mono();
+			tbool = mk_mono();
+			tstring = mk_mono();
+			tnull = (fun _ -> die "Could use locate abstract Null<T> (was it redefined?)" __LOC__);
+			tarray = (fun _ -> die "Could not locate class Array<T> (was it redefined?)" __LOC__);
+			titerator = (fun _ -> die "Could not locate typedef Iterator<T> (was it redefined?)" __LOC__);
+		};
+		local_wrapper = LocalWrapper.null_wrapper;
 		std = null_class;
+		module_to_file = new hashtbl_lookup;
+		parser_cache = new hashtbl_lookup;
+		overload_cache = new hashtbl_lookup; (* ! *)
+		is_macro_context = is_macro_context;
 		functional_interface_lut = new Lookup.hashtbl_lookup;
-		empty_class_path = new ClassPath.directory_class_path "" User;
-		class_paths = new ClassPaths.class_paths;
+		hxb_reader_api = None;
+		hxb_reader_stats = HxbReader.create_hxb_reader_stats ();
 	}
 
 let file_time file = Extc.filetime file
@@ -1059,4 +1141,4 @@ let make_unforced_lazy t_proc f where =
 			| Error.Error e ->
 				raise (Error.Fatal_error e)
 	);
-	r
+	r

+ 1 - 1
src/context/commonCache.ml

@@ -122,7 +122,7 @@ let rec cache_context cs com =
 		| None -> ()
 		| Some com -> cache_context cs com
 	end;
-	if Define.raw_defined com.defines "hxb.stats" then
+	if Define.defined com.defines HxbStats then
 		HxbReader.dump_stats (platform_name com.platform) com.hxb_reader_stats
 
 let maybe_add_context_sign cs com desc =

+ 5 - 7
src/context/display/deprecationCheck.ml

@@ -22,11 +22,9 @@ let warned_positions = Hashtbl.create 0
 let warn_deprecation dctx s p_usage =
 	let pkey p = (p.pfile,p.pmin) in
 	if not (Hashtbl.mem warned_positions (pkey p_usage)) then begin
-		Hashtbl.add warned_positions (pkey p_usage) (s,p_usage);
-		if not (is_diagnostics dctx.com) then begin
-			let options = Warning.from_meta (dctx.class_meta @ dctx.field_meta) in
-			module_warning dctx.com dctx.curmod WDeprecated options s p_usage;
-		end
+		let options = Warning.from_meta (dctx.class_meta @ dctx.field_meta) in
+		Hashtbl.add warned_positions (pkey p_usage) (s,p_usage,options);
+		module_warning dctx.com dctx.curmod WDeprecated options s p_usage;
 	end
 
 let print_deprecation_message dctx meta s p_usage =
@@ -101,7 +99,7 @@ let run_on_field dctx cf =
 	| _ ->
 		()
 
-let run com =
+let run com types =
 	let dctx = create_context com in
 	List.iter (fun t -> match t with
 		| TClassDecl c when not (Meta.has Meta.Deprecated c.cl_meta) ->
@@ -112,7 +110,7 @@ let run com =
 			List.iter (run_on_field dctx) c.cl_ordered_fields;
 		| _ ->
 			()
-	) com.types
+	) types
 
 let check_is com m cl_meta cf_meta name meta p =
 	let dctx = {

+ 7 - 3
src/context/display/diagnosticsPrinter.ml

@@ -183,9 +183,13 @@ let json_of_diagnostics com dctx =
 	(* non-append from here *)
 	begin match Warning.get_mode WDeprecated com.warning_options with
 	| WMEnable ->
-		Hashtbl.iter (fun _ (s,p) ->
-			let wobj = Warning.warning_obj WDeprecated in
-			add DKDeprecationWarning p MessageSeverity.Warning (Some wobj.w_name) (JString s);
+		Hashtbl.iter (fun _ (s,p,options) ->
+			begin match Warning.get_mode WDeprecated (com.warning_options @ options) with
+			| WMEnable ->
+				let wobj = Warning.warning_obj WDeprecated in
+				add DKDeprecationWarning p MessageSeverity.Warning (Some wobj.w_name) (JString s);
+			| WMDisable -> ()
+			end
 		) DeprecationCheck.warned_positions;
 	| WMDisable ->
 		()

+ 31 - 4
src/context/display/displayFields.ml

@@ -35,7 +35,7 @@ let get_submodule_fields ctx path =
 	) tl in
 	tl
 
-let collect_static_extensions ctx items e p =
+let collect_static_extensions ctx blocked_items items e p =
 	let opt_type t =
 		match t with
 		| TLazy f ->
@@ -81,7 +81,13 @@ let collect_static_extensions ctx items e p =
 			end
 		| _ ->
 			acc
-		in
+	in
+	let handle_field c cf acc =
+		if Hashtbl.mem blocked_items cf.cf_name then
+			acc
+		else
+			handle_field c cf acc
+	in
 	let rec loop acc = function
 		| [] ->
 			acc
@@ -142,6 +148,17 @@ let collect ctx e_ast e dk with_type p =
 		let ct = CompletionType.from_type (get_import_status ctx) ~values:(get_value_meta cf.cf_meta) cf.cf_type in
 		make_ci_class_field (CompletionClassField.make cf CFSMember origin true) (cf.cf_type,ct)
 	in
+	let blocked_items = Hashtbl.create 0 in
+	let should_access c cf stat =
+		if Hashtbl.mem blocked_items cf.cf_name then
+			false
+		else if should_access c cf stat then
+			true
+		else begin
+			Hashtbl.add blocked_items cf.cf_name ();
+			false
+		end
+	in
 	let rec loop items t =
 		let is_new_item items name = not (PMap.mem name items) in
 		let rec browse_interfaces c acc =
@@ -345,7 +362,7 @@ let collect ctx e_ast e dk with_type p =
 	(* Collect fields of the type *)
 	let items = loop items e.etype in
 	(* Add static extensions *)
-	let items = collect_static_extensions ctx items e p in
+	let items = collect_static_extensions ctx blocked_items items e p in
 	let items = PMap.fold (fun item acc -> item :: acc) items [] in
 	let items = sort_fields items WithType.value (TKField p) in
 	try
@@ -358,7 +375,17 @@ let collect ctx e_ast e dk with_type p =
 let handle_missing_field_raise ctx tthis i mode with_type pfield =
 	let tret = match with_type with
 		| WithType.WithType(t,_) -> t
-		| WithType.Value _ -> mk_mono()
+		| WithType.Value _ ->
+			begin match mode with
+				| MSet (Some e) ->
+					begin try
+						let e = type_expr ctx e WithType.value in
+						e.etype
+					with _ ->
+						mk_mono()
+					end
+				| _ -> mk_mono()
+			end
 		| WithType.NoValue ->
 			match mode with
 			| MCall _ -> ctx.t.tvoid

+ 3 - 0
src/context/display/displayMemory.ml

@@ -7,6 +7,8 @@ open Type
 let get_memory_json (cs : CompilationCache.t) mreq =
 	begin match mreq with
 	| MCache ->
+		let t0 = Extc.time() in
+		let stats = Gc.stat() in
 		let old_gc = Gc.get() in
 		Gc.set { old_gc with
 			Gc.max_overhead = 0;
@@ -14,6 +16,7 @@ let get_memory_json (cs : CompilationCache.t) mreq =
 		};
 		Gc.compact();
 		Gc.set old_gc;
+		ServerMessage.gc_stats (Extc.time() -. t0) stats true 0;
 		let stat = Gc.quick_stat() in
 		let size = (float_of_int stat.Gc.heap_words) *. (float_of_int (Sys.word_size / 8)) in
 		let cache_mem = cs#get_pointers in

+ 1 - 1
src/context/display/findReferences.ml

@@ -39,7 +39,7 @@ let rec collect_reference_positions com (name,pos,kind) =
 			| Var vk ->
 				let host = FieldAccess.get_host c cf in
 				let check r mode = match r with
-					| AccCall ->
+					| AccCall | AccPrivateCall ->
 						begin match FieldAccess.find_accessor_for_field host cf cf.cf_type mode with
 						| AccessorFound (cf_acc,new_host) ->
 							let c_host = FieldAccess.get_host_class_raise new_host in

+ 0 - 1
src/context/display/statistics.ml

@@ -1,7 +1,6 @@
 open Globals
 open Type
 open Common
-open Typecore
 open DisplayTypes
 
 type relation =

+ 17 - 0
src/context/dotGraph.ml

@@ -0,0 +1,17 @@
+open SafeCom
+
+let platform_name_macro com =
+	if Define.defined com.defines Define.Macro then "macro"
+	else Globals.platform_name com.platform
+
+let get_dump_path com path name =
+	com.dump_config.dump_path :: [platform_name_macro com] @ (fst path) @ [Printf.sprintf "%s.%s" (snd path) name]
+
+let start_graph ?(graph_config=[]) base_path suffix =
+	let ch = Path.create_file false suffix [] base_path in
+	Printf.fprintf ch "digraph graphname {\n";
+	List.iter (fun s -> Printf.fprintf ch "%s;\n" s) graph_config;
+	ch,(fun () ->
+		Printf.fprintf ch "}\n";
+		close_out ch
+	)

+ 32 - 14
src/context/parallel.ml

@@ -1,21 +1,36 @@
+let enable = ref false
+
 let run_parallel_for num_domains ?(chunk_size=0) length f =
-	let pool = Domainslib.Task.setup_pool ~num_domains:(num_domains - 1) () in
-	Domainslib.Task.run pool (fun _ -> Domainslib.Task.parallel_for pool ~chunk_size ~start:0 ~finish:(length-1) ~body:f);
-	Domainslib.Task.teardown_pool pool
+	if not !enable then begin
+		for i = 0 to length - 1 do
+			f i
+		done
+	end else
+		let pool = Domainslib.Task.setup_pool ~num_domains:(num_domains - 1) () in
+		Domainslib.Task.run pool (fun _ -> Domainslib.Task.parallel_for pool ~chunk_size ~start:0 ~finish:(length-1) ~body:f);
+		Domainslib.Task.teardown_pool pool
 
 module ParallelArray = struct
 	let iter pool f a =
-		let f' idx = f a.(idx) in
-		Domainslib.Task.parallel_for pool ~start:0 ~finish:(Array.length a - 1) ~body:f'
+		match pool with
+		| None ->
+			Array.iter f a
+		| Some pool ->
+			let f' idx = f a.(idx) in
+			Domainslib.Task.parallel_for pool ~start:0 ~finish:(Array.length a - 1) ~body:f'
 
 	let map pool f a x =
-		let length = Array.length a in
-		let a_out = Array.make length x in
-		let f' idx =
-			Array.unsafe_set a_out idx (f (Array.unsafe_get a idx))
-		in
-		Domainslib.Task.parallel_for pool ~start:0 ~finish:(length - 1) ~body:f';
-		a_out
+		match pool with
+		| None ->
+			Array.map f a
+		| Some pool ->
+			let length = Array.length a in
+			let a_out = Array.make length x in
+			let f' idx =
+				Array.unsafe_set a_out idx (f (Array.unsafe_get a idx))
+			in
+			Domainslib.Task.parallel_for pool ~start:0 ~finish:(length - 1) ~body:f';
+			a_out
 end
 
 module ParallelSeq = struct
@@ -24,5 +39,8 @@ module ParallelSeq = struct
 end
 
 let run_in_new_pool timer_ctx f =
-	let pool = Timer.time timer_ctx ["domainslib";"setup"] (Domainslib.Task.setup_pool ~num_domains:(Domain.recommended_domain_count() - 1)) () in
-	Std.finally (fun () -> Timer.time timer_ctx ["domainslib";"teardown"] Domainslib.Task.teardown_pool pool) (Domainslib.Task.run pool) (fun () -> f pool)
+	if not !enable then
+		f None
+	else
+		let pool = Timer.time timer_ctx ["domainslib";"setup"] (Domainslib.Task.setup_pool ~num_domains:(Domain.recommended_domain_count() - 1)) () in
+		Std.finally (fun () -> Timer.time timer_ctx ["domainslib";"teardown"] Domainslib.Task.teardown_pool pool) (Domainslib.Task.run pool) (fun () -> f (Some pool))

+ 1 - 1
src/context/safeCom.ml

@@ -5,7 +5,7 @@ open PlatformConfig
 type saved_warning = {
 	w_module : module_def;
 	w_warning : WarningList.warning;
-	w_options : Warning.warning_option list list;
+	w_options : warning_option list list;
 	w_msg : string;
 	w_pos : pos;
 }

+ 20 - 6
src/context/typecore.ml

@@ -90,6 +90,10 @@ type typer_pass_tasks = {
 	mutable tasks : (unit -> unit) list;
 }
 
+type function_mode =
+	| FunFunction
+	| FunNotFunction
+
 type typer_globals = {
 	mutable delayed : typer_pass_tasks Array.t;
 	mutable delayed_min_index : int;
@@ -122,7 +126,7 @@ type typer_globals = {
    is shared by local TFunctions. *)
 and typer_expr = {
 	curfun : current_fun;
-	in_function : bool;
+	function_mode : function_mode;
 	mutable ret : t;
 	mutable opened : anon_status ref list;
 	mutable monomorphs : (tmono * pos) list;
@@ -215,10 +219,10 @@ module TyperManager = struct
 			in_call_args = false;
 		}
 
-	let create_ctx_e curfun in_function =
+	let create_ctx_e curfun function_mode =
 		{
 			curfun;
-			in_function;
+			function_mode;
 			ret = t_dynamic;
 			opened = [];
 			monomorphs = [];
@@ -281,8 +285,14 @@ module TyperManager = struct
 
 	let clone_for_type_parameter_expression ctx =
 		let f = create_ctx_f ctx.f.curfield in
-		let e = create_ctx_e ctx.e.curfun false in
+		let e = create_ctx_e ctx.e.curfun FunNotFunction in
 		create ctx ctx.m ctx.c f e PTypeField ctx.type_params
+
+	let is_function_context ctx = match ctx.e.function_mode with
+		| FunFunction ->
+			true
+		| FunNotFunction ->
+			false
 end
 
 type field_host =
@@ -507,8 +517,12 @@ let needs_inline ctx c cf =
 	cf.cf_kind = Method MethInline && ctx.allow_inline && (ctx.com.doinline || is_forced_inline c cf)
 
 (** checks if we can access to a given class field using current context *)
-let can_access ctx c cf stat =
-	if (has_class_field_flag cf CfPublic) then
+let can_access ctx c cf ?(check_prop=false) ?(is_setter=false) stat =
+	let is_private_prop = check_prop && match cf.cf_kind with
+		| Var { v_read = AccPrivateCall } when not is_setter -> true
+		| Var { v_write = AccPrivateCall } when is_setter -> true
+		| _ -> false in
+	if (not is_private_prop && has_class_field_flag cf CfPublic) then
 		true
 	else if c == ctx.c.curclass then
 		true

+ 4 - 7
src/core/define.ml

@@ -155,16 +155,13 @@ let get_signature def =
 	| None ->
 		let defines = PMap.foldi (fun k v acc ->
 			(* don't make much difference between these special compilation flags *)
-			match String.concat "_" (ExtString.String.nsplit k "-") with
+			let sanitized = String.concat "_" (ExtString.String.nsplit k "-") in
 			(* If we add something here that might be used in conditional compilation it should be added to
-			   Parser.parse_macro_ident as well (issue #5682).
-			   Note that we should removed flags like use_rtti_doc here.
+			   Grammar.parse_macro_ident as well (issue #5682).
 			*)
-			| "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin" | "disable-hxb-cache" | "hxb.stats" | "fail_fast"
-			| "message.reporting" | "message.log_file" | "message.log_format" | "message.no_color"
-			| "dump" | "dump_dependencies" | "dump_ignore_var_ids" -> acc
-			| _ -> (k ^ "=" ^ v) :: acc
+			if DefineList.is_signature_neutral sanitized then acc else (sanitized ^ "=" ^ v) :: acc
 		) def.values [] in
+		let defines = Ast.remove_duplicates (fun a b -> a != b) defines in
 		let str = String.concat "@" (List.sort compare defines) in
 		let s = Digest.string str in
 		def.defines_signature <- Some s;

+ 0 - 11
src/core/display/completionItem.ml

@@ -55,10 +55,6 @@ module CompletionModuleType = struct
 		| No
 		| Maybe
 
-	type module_type_source =
-		| Syntax of type_def (* TODO: do we really want to keep this? *)
-		| Typed of module_type
-
 	type t = {
 		pack : string list;
 		name : string;
@@ -73,7 +69,6 @@ module CompletionModuleType = struct
 		is_abstract : bool;
 		kind : CompletionModuleKind.t;
 		has_constructor : not_bool;
-		source : module_type_source;
 	}
 
 	let of_type_decl pack module_name (td,p) = match td with
@@ -101,7 +96,6 @@ module CompletionModuleType = struct
 				is_abstract = List.mem HAbstract d.d_flags;
 				kind = if List.mem HInterface d.d_flags then Interface else Class;
 				has_constructor = ctor;
-				source = Syntax td;
 			}
 		| EEnum d -> {
 				pack = pack;
@@ -117,7 +111,6 @@ module CompletionModuleType = struct
 				is_abstract = false;
 				kind = Enum;
 				has_constructor = No;
-				source = Syntax td;
 			}
 		| ETypedef d ->
 			let kind = match fst d.d_data with CTAnonymous _ -> Struct | _ -> TypeAlias in
@@ -135,7 +128,6 @@ module CompletionModuleType = struct
 				is_abstract = false;
 				kind = kind;
 				has_constructor = if kind = Struct then No else Maybe;
-				source = Syntax td;
 			}
 		| EAbstract d ->
 			let ctor =
@@ -159,7 +151,6 @@ module CompletionModuleType = struct
 				is_abstract = false;
 				kind = if List.mem AbEnum d.d_flags then EnumAbstract else Abstract;
 				has_constructor = ctor;
-				source = Syntax td;
 			}
 		| EStatic d ->
 			{
@@ -176,7 +167,6 @@ module CompletionModuleType = struct
 				is_abstract = false;
 				kind = Static;
 				has_constructor = No;
-				source = Syntax td;
 			}
 		| EImport _ | EUsing _ ->
 			raise Exit
@@ -243,7 +233,6 @@ module CompletionModuleType = struct
 			is_abstract = is_abstract;
 			kind = kind;
 			has_constructor = ctor;
-			source = Typed mt;
 		}
 
 	let get_path cm = (cm.pack,cm.name)

+ 12 - 0
src/core/ds/threadSafeHashtbl.ml

@@ -17,6 +17,18 @@ let replace h k v =
 let find h k =
 	Mutex.protect h.mutex (fun () -> Hashtbl.find h.h) k
 
+let find_or_add h k f =
+	Mutex.lock h.mutex;
+	try
+		let r = Hashtbl.find h.h k in
+		Mutex.unlock h.mutex;
+		r
+	with Not_found ->
+		let r = f () in
+		Hashtbl.add h.h k r;
+		Mutex.unlock h.mutex;
+		r
+
 let mem h k =
 	Mutex.protect h.mutex (fun () -> Hashtbl.mem h.h) k
 

+ 2 - 1
src/core/json/genjson.ml

@@ -497,6 +497,7 @@ and generate_class_field' ctx cfs cf =
 				| AccNever -> "AccNever",None
 				| AccCtor -> "AccCtor",None
 				| AccCall -> "AccCall",None
+				| AccPrivateCall -> "AccPrivateCall",None
 				| AccInline -> "AccInline",None
 				| AccRequire(s,so) -> "AccRequire",Some (jobject ["require",jstring s;"message",jopt jstring so])
 			in
@@ -736,4 +737,4 @@ let generate timer_ctx types file =
 		let ch = open_out_bin file in
 		Json.write_json (output_string ch) json;
 		close_out ch;
-	) ()
+	) ()

+ 1 - 1
src/core/tOther.ml

@@ -58,7 +58,7 @@ module TExprToExpr = struct
 								| AccNormal | AccCtor | AccInline | AccRequire _ -> "default"
 								| AccNo -> "null"
 								| AccNever -> "never"
-								| AccCall -> get_or_set
+								| AccCall | AccPrivateCall -> get_or_set
 							in
 							let read = (var_access_to_string v.v_read "get",null_pos) in
 							let write = (var_access_to_string v.v_write "set",null_pos) in

+ 1 - 0
src/core/tPrinting.ml

@@ -164,6 +164,7 @@ let s_access is_read = function
 	| AccNo -> "null"
 	| AccNever -> "never"
 	| AccCall -> if is_read then "get" else "set"
+	| AccPrivateCall -> if is_read then "private get" else "private set"
 	| AccInline	-> "inline"
 	| AccRequire (n,_) -> "require " ^ n
 	| AccCtor -> "ctor"

+ 11 - 1
src/core/tType.ml

@@ -16,6 +16,7 @@ and var_access =
 	| AccNever          (* can't be accessed, even in subclasses *)
 	| AccCtor           (* can only be accessed from the constructor *)
 	| AccCall           (* perform a method call when accessed *)
+	| AccPrivateCall    (* perform a method call when accessed, but private like AccNo *)
 	| AccInline         (* similar to Normal but inline when accessed *)
 	| AccRequire of string * string option (* set when @:require(cond) fails *)
 
@@ -59,10 +60,19 @@ type type_param_host =
 	| TPHLocal
 	| TPHUnbound
 
+type warning_mode =
+	| WMEnable
+	| WMDisable
+
+type warning_option = {
+	wo_warning : WarningList.warning;
+	wo_mode : warning_mode;
+}
+
 type cache_bound_object =
 	| Resource of string * string
 	| IncludeFile of string * string
-	| Warning of WarningList.warning * string * pos
+	| Warning of WarningList.warning * (warning_option list list) * string * pos
 
 type t =
 	| TMono of tmono

+ 4 - 3
src/core/tUnification.ml

@@ -511,11 +511,12 @@ let unify_access a1 a2 =
 	a1 = a2 || match a1, a2 with
 	| _, AccNo | _, AccNever -> true
 	| AccInline, AccNormal -> true
+	| AccCall, AccPrivateCall -> true
 	| _ -> false
 
 let direct_access = function
 	| AccNo | AccNever | AccNormal | AccInline | AccRequire _ | AccCtor -> true
-	| AccCall -> false
+	| AccCall | AccPrivateCall -> false
 
 let unify_kind ~(strict:bool) k1 k2 =
 	k1 = k2 || match k1, k2 with
@@ -908,8 +909,8 @@ let rec unify (uctx : unification_context) a b =
 							with Not_found ->
 								()
 						in
-						(match vk.v_read with AccCall -> check ("get_" ^ f1.cf_name) | _ -> ());
-						(match vk.v_write with AccCall -> check ("set_" ^ f1.cf_name) | _ -> ());
+						(match vk.v_read with AccCall | AccPrivateCall -> check ("get_" ^ f1.cf_name) | _ -> ());
+						(match vk.v_write with AccCall | AccPrivateCall -> check ("set_" ^ f1.cf_name) | _ -> ());
 					| _ -> ()
 				end;
 				(match f1.cf_kind with

+ 10 - 0
src/core/texpr.ml

@@ -547,6 +547,16 @@ module Builder = struct
 	let index basic e index t p =
 		mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) basic.tint p)) t p
 
+	let default_value t p = match follow_without_null t with
+		| TAbstract({a_path = ([],"Int")},[]) ->
+			mk (TConst (TInt (Int32.zero))) t p
+		| TAbstract({a_path = ([],"Float")},[]) ->
+			mk (TConst (TFloat "0.0")) t p
+		| TAbstract({a_path = ([],"Bool")},[]) ->
+			mk (TConst (TBool false)) t p
+		| _ ->
+			mk (TConst TNull) t p
+
 	let resolve_and_make_static_call c name args p =
 		ignore(c.cl_build());
 		let cf = try

+ 1 - 9
src/core/warning.ml

@@ -1,16 +1,8 @@
 open Globals
 open Error
+open TType
 include WarningList
 
-type warning_mode =
-	| WMEnable
-	| WMDisable
-
-type warning_option = {
-	wo_warning : warning;
-	wo_mode : warning_mode;
-}
-
 let parse_options lctx s ps lexbuf =
 	let fail msg p =
 		raise_typing_error msg {p with pmin = ps.pmin + p.pmin; pmax = ps.pmin + p.pmax}

+ 2 - 1
src/filters/exception/saveStacks.ml

@@ -111,7 +111,8 @@ let patch_constructors ectx =
 							}
 						| _ -> die "" __LOC__
 					)
-				| None -> die "" __LOC__
+				| None ->
+					raise_typing_error "Could not patch constructor on this function because there isn't one" cls.cl_name_pos
 				| _ -> ()
 				)
 			| _ -> ()

+ 8 - 8
src/filters/filters.ml

@@ -417,9 +417,9 @@ let might_need_cf_unoptimized c cf =
 	| _ ->
 		has_class_field_flag cf CfGeneric
 
-let run_safe_filters ectx com (scom : SafeCom.t) new_types_array cv_wrapper_impl rename_locals_config pool =
+let run_safe_filters ectx com (scom : SafeCom.t) all_types_array new_types_array rename_locals_config pool =
 	let detail_times = Timer.level_from_define scom.defines Define.FilterTimes in
-
+	let cv_wrapper_impl = com.Common.local_wrapper in
 	let filters_before_inlining = [
 		"handle_abstract_casts",AbstractCast.handle_abstract_casts;
 		"local_statics",LocalStatic.run;
@@ -454,7 +454,7 @@ let run_safe_filters ectx com (scom : SafeCom.t) new_types_array cv_wrapper_impl
 	Dump.maybe_generate_dump com AfterInlining;
 
 	Common.enter_stage com CAnalyzerStart;
-	if scom.platform <> Cross then Analyzer.Run.run_on_types scom pool new_types_array;
+	if scom.platform <> Cross then Analyzer.Run.run_on_types scom pool all_types_array new_types_array;
 	Dump.maybe_generate_dump com AfterAnalyzing;
 	Common.enter_stage com CAnalyzerDone;
 
@@ -491,6 +491,7 @@ let run com ectx main before_destruction =
 		not cached
 	) com.types in
 	let new_types_array = Array.of_list new_types in
+	let all_types_array = Array.of_list com.types in
 
 	(* IMPORTANT:
 	    There may be types in new_types which have already been post-processed, but then had their m_processed flag unset
@@ -498,15 +499,15 @@ let run com ectx main before_destruction =
 		It is important that all filters from here up to save_class_state only process fields which do not have the
 		CfPostProcessed flag set.
 
-		This is mostly covered by run_expression_filters already, but any new additions which don't utilize that have to
-		be aware of this.
+		This is mostly covered by run_expression_filters_safe already, but any new additions which don't utilize that have
+		to be aware of this.
 	*)
+	DeprecationCheck.run com new_types;
 	NullSafety.run com new_types;
-	let cv_wrapper_impl = CapturedVars.get_wrapper_implementation com in
 	let rename_locals_config = RenameVars.init scom.SafeCom.platform_config com.types in
 	Parallel.run_in_new_pool scom.timer_ctx (fun pool ->
 		SafeCom.run_with_scom com scom (fun () ->
-			run_safe_filters ectx com scom new_types_array cv_wrapper_impl rename_locals_config pool
+			run_safe_filters ectx com scom all_types_array new_types_array rename_locals_config pool
 		)
 	);
 	with_timer com.timer_ctx detail_times "callbacks" None (fun () ->
@@ -528,5 +529,4 @@ let run com ectx main before_destruction =
 		com.callbacks#run com.error_ext com.callbacks#get_after_save;
 	);
 	before_destruction();
-	let all_types_array = Array.of_list com.types in
 	destruction com scom ectx detail_times main rename_locals_config com.types all_types_array

+ 0 - 1
src/filters/filtersCommon.ml

@@ -16,7 +16,6 @@
 	along with this program; if not, write to the Free Software
 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *)
-open Globals
 open Type
 open Common
 open Typecore

+ 28 - 52
src/filters/safe/capturedVars.ml

@@ -16,56 +16,10 @@
 	along with this program; if not, write to the Free Software
 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *)
-open Globals
 open SafeCom
 open Type
 open LocalUsage
 
-let get_wrapper_implementation com =
-	let t = com.Common.basic in
-	match com.platform with
-	(* optimized version for Java - use native arrays *)
-	| Jvm ->
-		let cnativearray =
-			match (List.find (fun md -> match md with
-					| TClassDecl ({ cl_path = ["jvm"],"NativeArray" }) -> true
-					| _ -> false
-				) com.types)
-			with TClassDecl cl -> cl | _ -> die "" __LOC__
-		in
-
-		object
-			method captured_type t = TInst (cnativearray,[t])
-
-			method mk_ref v ve p =
-				match ve with
-				| None ->
-					let eone = mk (TConst (TInt (Int32.of_int 1))) t.tint p in
-					let t = match v.v_type with TInst (_, [t]) -> t | _ -> die "" __LOC__ in
-					mk (TNew (cnativearray,[t],[eone])) v.v_type p
-				| Some e ->
-					{ (Inline.mk_untyped_call "__array__" p [e]) with etype = v.v_type }
-
-			method mk_ref_access e v =
-				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
-
-			method mk_init av v pos =
-				let elocal = mk (TLocal v) v.v_type pos in
-				let earray = { (Inline.mk_untyped_call "__array__" pos [elocal]) with etype = av.v_type } in
-				mk (TVar (av,Some earray)) t.tvoid pos
-		end
-	(* default implementation - use haxe array *)
-	| _ ->
-		object
-			method captured_type = t.tarray
-			method mk_ref v ve p =
-				mk (TArrayDecl (match ve with None -> [] | Some e -> [e])) v.v_type p
-			method mk_ref_access e v =
-				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
-			method mk_init av v pos =
-				mk (TVar (av,Some (mk (TArrayDecl [mk (TLocal v) v.v_type pos]) av.v_type pos))) t.tvoid pos
-		end
-
 (* BLOCK VARIABLES CAPTURE *)
 (*
 	For some platforms, it will simply mark the variables which are used in closures
@@ -225,8 +179,26 @@ let captured_vars scom impl e =
 	and all_vars e =
 		let vars = ref PMap.empty in
 		let used = ref PMap.empty in
+		let in_loop = ref false in
+		let loop_vars = ref PMap.empty in
 		let assigned = ref PMap.empty in
 		let depth = ref 0 in
+		let mark_assigned v =
+			assigned := PMap.add v.v_id v !assigned;
+			(* Remove from vars lookup because we're done with it *)
+			vars := PMap.remove v.v_id !vars;
+		in
+		let check_loop_var v is_assign =
+			try
+				let is_assign' = PMap.find v.v_id !loop_vars in
+				(* If we have both read and write in the same loop we need to wrap. *)
+				if is_assign <> is_assign' then mark_assigned v
+			with Not_found ->
+				loop_vars := PMap.add v.v_id is_assign !loop_vars
+		in
+		let check_loop_var v is_assign =
+			if !in_loop then check_loop_var v is_assign
+		in
 		let rec collect_vars = function
 		| Block f ->
 			let old = !vars in
@@ -234,7 +206,12 @@ let captured_vars scom impl e =
 			vars := old;
 		| Loop f ->
 			let old = !vars in
+			let old_loop_vars = !loop_vars in
+			let old_loop = !in_loop in
+			in_loop := true;
 			f collect_vars;
+			in_loop := old_loop;
+			loop_vars := old_loop_vars;
 			vars := old;
 		| Function f ->
 			incr depth;
@@ -246,8 +223,8 @@ let captured_vars scom impl e =
 			(try
 				let d = PMap.find v.v_id !vars in
 				if d <> !depth then begin
+					check_loop_var v false;
 					used := PMap.add v.v_id v !used;
-					if has_var_flag v VAssigned then assigned := PMap.add v.v_id v !assigned;
 				end
 			with Not_found -> ())
 		| Assign v ->
@@ -256,13 +233,12 @@ let captured_vars scom impl e =
 				(* different depth - needs wrap *)
 				if d <> !depth then begin
 					used := PMap.add v.v_id v !used;
-					assigned := PMap.add v.v_id v !assigned;
-				end
+					mark_assigned v
 				(* same depth but assigned after being used on a different depth - needs wrap *)
-				else if PMap.mem v.v_id !used then
-					assigned := PMap.add v.v_id v !assigned
+				end else if PMap.mem v.v_id !used then
+					mark_assigned v
 				else
-					add_var_flag v VAssigned;
+					check_loop_var v true
 			with Not_found -> ())
 		in
 		local_usage collect_vars e;

+ 8 - 8
src/generators/cpp/cppRetyper.ml

@@ -1505,7 +1505,7 @@ let get_id path ids =
   | None ->
     let new_id = make_id 0 in
     (new_id, ObjectIds.add path new_id ids)
-  
+
 let native_field_name_remap field =
   match get_meta_string field.cf_meta Meta.Native with
   | Some nativeImpl ->
@@ -1533,7 +1533,7 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
     tcv_type = field.cf_type;
     tcv_default = None;
 
-    tcv_has_getter = (match field.cf_kind with | Var { v_read = AccCall } -> true | _ -> false);
+    tcv_has_getter = (match field.cf_kind with | Var { v_read = AccCall | AccPrivateCall } -> true | _ -> false);
     tcv_is_stackonly = has_meta Meta.StackOnly field.cf_meta;
     tcv_is_reflective = reflective class_def field;
     tcv_is_gc_element = cpp_type_of field.cf_type |> is_gc_element ctx;
@@ -1567,14 +1567,14 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
             (* We can't implement abstract functions as pure virtual due to cppia needing to construct the class *)
             let map_arg (name, _, t) =
               ( (alloc_var VGenerated name t null_pos), (get_default_value name) ) in
-            let expr = 
+            let expr =
               match follow ret with
               | TAbstract ({ a_path = ([], "Void") }, _) ->
                 { eexpr = TReturn None; etype = ret; epos = null_pos }
               | _ ->
                 let zero_val = Some { eexpr = TConst (TInt Int32.zero); etype = ret; epos = null_pos } in
                 { eexpr = TReturn zero_val; etype = ret; epos = null_pos } in
-            
+
             {
               tf_args = args |> List.map map_arg;
               tf_type = ret;
@@ -1611,7 +1611,7 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
       | Var _, _ ->
         Some (create_variable field)
       (* Dynamic methods are implemented as a physical field holding a closure *)
-      | Method MethDynamic, Some { eexpr = TFunction func } -> 
+      | Method MethDynamic, Some { eexpr = TFunction func } ->
         Some (create_variable { field with cf_expr = None; cf_kind = Var ({ v_read = AccNormal; v_write = AccNormal }) })
       (* Below should cause abstracts which have functions with no implementation to be generated as a field *)
       (* See Int32.hx as an example *)
@@ -1631,7 +1631,7 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
       None in
 
   let id, ids = get_id class_def.cl_path ids in
-  
+
   let static_functions =
     class_def.cl_ordered_statics
     |> List.filter_map (filter_functions true) in
@@ -1650,7 +1650,7 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
     |> List.filter (fun field -> field.cf_name <> "__meta__" && field.cf_name <> "__rtti")
     |> List.filter_map filter_properties in
 
-  let functions = 
+  let functions =
     class_def.cl_ordered_fields
     |> List.filter_map (filter_functions true) in
 
@@ -1822,4 +1822,4 @@ and tcpp_enum_from_tenum ctx ids enum_def =
   in
   let enum = { te_enum = enum_def; te_id = self_id; te_constructors = constructors } in
 
-  (ids, enum)
+  (ids, enum)

+ 1 - 1
src/generators/cpp/gen/cppCppia.ml

@@ -1799,7 +1799,7 @@ let generate_script_class common_ctx script class_def =
           | AccNormal | AccCtor -> IaAccessNormal
           | AccNo -> IaAccessNot
           | AccNever -> IaAccessNot
-          | AccCall ->
+          | AccCall | AccPrivateCall ->
               if
                 Meta.has Meta.NativeProperty class_def.cl_meta
                 || Meta.has Meta.NativeProperty field.cf_meta

+ 13 - 13
src/generators/cpp/gen/cppGenClassImplementation.ml

@@ -47,7 +47,7 @@ let gen_function ctx class_def class_name is_static func =
       (gen_cpp_function_body ctx class_def is_static func.tcf_field.cf_name func.tcf_func code tail_code);
 
     output "\n\n";
-    
+
     (* generate dynamic version too ... *)
     if (not func.tcf_is_virtual || not func.tcf_is_overriding) && func.tcf_is_reflective then
       let tcpp_args = List.map (fun (v, _) -> cpp_type_of v.v_type) func.tcf_func.tf_args in
@@ -85,7 +85,7 @@ let gen_function ctx class_def class_name is_static func =
             Printf.sprintf "(::cpp::Struct< %s >) a%i" (tcpp_to_string arg) idx
           | _ ->
             Printf.sprintf "a%i" idx in
-            
+
         tcpp_args
         |> ExtList.List.mapi cast_prefix
         |> String.concat ", "
@@ -120,7 +120,7 @@ let gen_dynamic_function ctx class_def class_name is_static is_for_static_var (f
   let ret = if is_void then "(void)" else "return " in
 
   ctx.ctx_real_this_ptr <- false;
-  Printf.sprintf "HX_BEGIN_DEFAULT_FUNC(%s, %s)\n" func_name class_name |> output; 
+  Printf.sprintf "HX_BEGIN_DEFAULT_FUNC(%s, %s)\n" func_name class_name |> output;
   Printf.sprintf "%s _hx_run(%s)" return_type_str (print_arg_list func.tcf_func.tf_args "__o_") |> output;
 
   gen_cpp_function_body ctx class_def is_static func_name func.tcf_func "" "" no_debug;
@@ -273,7 +273,7 @@ let generate_native_class base_ctx tcpp_class =
   output_cpp "\n";
 
   gen_dynamic_function_allocator ctx output_cpp tcpp_class;
-  
+
   generate_native_constructor ctx output_cpp class_def false;
   gen_boot_field ctx output_cpp tcpp_class;
 
@@ -394,13 +394,13 @@ let generate_managed_class base_ctx tcpp_class =
     let impl_name = cpp_class_name class_def in
 
     let fold_interface (glued, acc) interface =
-    
+
       let rec gen_interface_funcs interface =
 
         let fold_field (glued, acc) func =
           let cast      = cpp_tfun_signature false func.iff_args func.iff_return in
           let real_name = cpp_member_name_of func.iff_field in
-          
+
           (* C++ can't work out which function it needs to take the addrss of
               when the implementation is overloaded - currently the map-set functions.
               Change the castKey to force a glue function in this case (could double-cast the pointer, but it is ugly)
@@ -452,7 +452,7 @@ let generate_managed_class base_ctx tcpp_class =
       let call     = Printf.sprintf "static %s %s_%s = {\n%s\n};\n" (cpp_class_name interface.if_class) cname interface_name combined in
       (glued, call :: acc)
     in
-    
+
     let glued, calls =
       List.fold_left
         fold_interface
@@ -615,7 +615,7 @@ let generate_managed_class base_ctx tcpp_class =
     else
       acc
   in
-  
+
   let castable f =
     match cpp_type_of f.cf_type with
     | TCppInst (t, _) as inst when Meta.has Meta.StructAccess t.cl_meta ->
@@ -671,7 +671,7 @@ let generate_managed_class base_ctx tcpp_class =
           Printf.sprintf "%s = inValue.Cast< %s >(); return inValue;" var.tcv_name casted in
 
         match var.tcv_field.cf_kind with
-        | Var { v_write = AccCall } ->
+        | Var { v_write = AccCall | AccPrivateCall } ->
           let prop_call = checkPropCall var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let call      = Printf.sprintf "if (%s) { return ::hx::Val( %s(inValue.Cast< %s >()) ); } else { %s }" prop_call setter casted default in
@@ -690,7 +690,7 @@ let generate_managed_class base_ctx tcpp_class =
         let casted  = castable var.tcv_field in
 
         match var.tcv_field.cf_kind with
-        | Var { v_write = AccCall } ->
+        | Var { v_write = AccCall | AccPrivateCall } ->
           let prop_call = checkPropCall var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let call      = Printf.sprintf "if (%s) { return ::hx::Val( %s(inValue.Cast< %s >()) ); }" prop_call setter casted in
@@ -717,7 +717,7 @@ let generate_managed_class base_ctx tcpp_class =
         let casted = castable var.tcv_field in
 
         match var.tcv_field.cf_kind with
-        | Var { v_write = AccCall } ->
+        | Var { v_write = AccCall | AccPrivateCall } ->
           let prop_call = checkPropCall var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let call      = Printf.sprintf "if (%s) { ioValue = %s(ioValue.Cast< %s >()); } else { %s = ioValue.Cast< %s >(); } return true;" prop_call setter casted var.tcv_name casted in
@@ -734,7 +734,7 @@ let generate_managed_class base_ctx tcpp_class =
     let fold_property (var:tcpp_class_variable) acc =
       if var.tcv_is_reflective && not (is_abstract_impl class_def) then
         match var.tcv_field.cf_kind with
-        | Var { v_write = AccCall } ->
+        | Var { v_write = AccCall | AccPrivateCall } ->
           let prop_call = checkPropCall var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let casted    = castable var.tcv_field in
@@ -965,7 +965,7 @@ let generate_managed_class base_ctx tcpp_class =
           | _ -> [] in
         current_virtual_functions_rev cls initial
       in
-    
+
       flatten_tcpp_class_functions_rec tcpp_class |> List.rev
     in
 

+ 4 - 4
src/generators/flashProps.ml

@@ -29,8 +29,8 @@ let find_property_for_accessor ~isget cl tl accessor_name =
 		match Type.class_field cl tl prop_name with
 		| Some (prop_cl, prop_tl), _, prop_cf ->
 			(match prop_cf.cf_kind with
-			| Var { v_read = AccCall; v_write = AccCall | AccNever } when isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf)
-			| Var { v_read = AccCall | AccNever; v_write = AccCall } when not isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf)
+			| Var { v_read = AccCall | AccPrivateCall; v_write = AccCall | AccPrivateCall | AccNever } when isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf)
+			| Var { v_read = AccCall | AccPrivateCall | AccNever; v_write = AccCall | AccPrivateCall } when not isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf)
 			| _ -> None)
 		| _ -> None
 	with Not_found ->
@@ -47,8 +47,8 @@ let find_static_property_for_accessor ~isget cl accessor_name =
 	try
 		let prop_cf = PMap.find prop_name cl.cl_statics in
 		(match prop_cf.cf_kind with
-		| Var { v_read = AccCall; v_write = AccCall | AccNever } when isget && is_flash_property prop_cf -> Some prop_cf
-		| Var { v_read = AccCall | AccNever; v_write = AccCall } when not isget && is_flash_property prop_cf -> Some prop_cf
+		| Var { v_read = AccCall | AccPrivateCall; v_write = AccCall | AccPrivateCall | AccNever } when isget && is_flash_property prop_cf -> Some prop_cf
+		| Var { v_read = AccCall | AccPrivateCall | AccNever; v_write = AccCall | AccPrivateCall } when not isget && is_flash_property prop_cf -> Some prop_cf
 		| _ -> None)
 	with Not_found ->
 		None

+ 2 - 2
src/generators/gctx.ml

@@ -8,7 +8,7 @@ type context_main = {
 	mutable main_expr : texpr option;
 }
 
-type warning_function = ?depth:int -> ?from_macro:bool -> warning -> Warning.warning_option list list -> string -> pos -> unit
+type warning_function = ?depth:int -> ?from_macro:bool -> warning -> warning_option list list -> string -> pos -> unit
 type error_function = string -> pos -> unit
 
 type t = {
@@ -118,4 +118,4 @@ let get_es_version defines =
 let map_source_header defines f =
 	match Define.defined_value_safe defines Define.SourceHeader with
 	| "" -> ()
-	| s -> f s
+	| s -> f s

+ 14 - 15
src/generators/genhl.ml

@@ -333,18 +333,8 @@ let make_debug ctx arr =
 		| true -> if (Filename.is_relative p.pfile)
 			then Filename.concat (Sys.getcwd()) p.pfile
 			else p.pfile
-		| false -> try
-			(* lookup relative path *)
-			let len = String.length p.pfile in
-			let base = ctx.com.class_paths#find (fun path ->
-				let path = path#path in
-				let l = String.length path in
-				len > l && String.sub p.pfile 0 l = path
-			) in
-			let l = String.length base#path in
-			String.sub p.pfile l (len - l)
-		with Not_found ->
-			p.pfile
+		| false ->
+			ctx.com.class_paths#relative_path p.pfile
 	in
 	let pos = ref (0,0,Globals.null_pos) in
 	let cur_file = ref 0 in
@@ -783,6 +773,7 @@ and enum_class ctx e =
 					let old = ctx.m in
 					let ft = to_type ctx ef.ef_type in
 					ctx.m <- method_context eid ft null_capture false;
+					set_curpos ctx ef.ef_pos;
 					let arg_regs = List.map (fun t -> alloc_fresh ctx t) fargs in
 					let ret_reg = alloc_fresh ctx tret in
 					op ctx (OMakeEnum (ret_reg, ef.ef_index, arg_regs));
@@ -2408,8 +2399,14 @@ and eval_expr ctx e =
 		| HFun _ -> cast_to ctx r to_t e.epos
 		| _ -> unsafe_cast_to ctx r to_t e.epos)
 	| TObjectDecl fl ->
-		(match to_type ctx e.etype with
-		| HVirtual vp as t when Array.length vp.vfields = List.length fl && not (List.exists (fun ((s,_,_),e) -> (try ignore(PMap.find s vp.vindex); false with Not_found -> true) || (s = "toString" && is_to_string e.etype)) fl) ->
+		(* We cannot rely on e.etype because it might have optional field etc, see jvm *)
+		let fields = List.fold_left (fun acc ((name,_,_),e) ->
+			let cf = mk_field name e.etype e.epos e.epos in
+			PMap.add name cf acc
+		) PMap.empty fl in
+		let rt = to_type ctx (mk_anon ~fields (ref Closed)) in
+		(match rt with
+		| HVirtual vp as t when safe_cast rt (to_type ctx e.etype) && not (List.exists (fun ((s,_,_),e) -> s = "toString" && is_to_string e.etype) fl) ->
 			let r = alloc_tmp ctx t in
 			op ctx (ONew r);
 			hold ctx r;
@@ -3284,6 +3281,7 @@ and gen_method_wrapper ctx rt t p =
 		let targs, tret = (match t with HFun (args, ret) -> args, ret | _ -> die "" __LOC__) in
 		let iargs, iret = (match rt with HFun (args, ret) -> args, ret | _ -> die "" __LOC__) in
 		ctx.m <- method_context fid HDyn null_capture false;
+		set_curpos ctx p;
 		let rfun = alloc_tmp ctx rt in
 		let rargs = List.map (fun t ->
 			let r = alloc_tmp ctx t in
@@ -3831,7 +3829,8 @@ let generate_static_init ctx types main =
 	| Some e -> exprs := e :: !exprs);
 	let fid = lookup_alloc ctx.cfids () in
 	let exprs = List.rev !init_exprs @ List.rev !exprs in
-	ignore(make_fun ~gen_content ctx ("","") fid { tf_expr = mk (TBlock exprs) t_void null_pos; tf_args = []; tf_type = t_void } None None);
+	let initpos = fake_pos "fun$init" in
+	ignore(make_fun ~gen_content ctx ("","") fid { tf_expr = mk (TBlock exprs) t_void initpos; tf_args = []; tf_type = t_void } None None);
 	fid
 
 (* --------------------------------------------------------------------------------------------------------------------- *)

+ 1 - 1
src/generators/genjvm.ml

@@ -1963,7 +1963,7 @@ class texpr_to_jvm
 		if not jm#is_terminated then self#texpr' ret e
 
 	method texpr' ret e =
-		code#set_line (Lexer.get_error_line_if_exists e.epos);
+		code#set_line (Lexer.get_error_line e.epos);
 		match e.eexpr with
 		| TVar(v,Some e1) ->
 			self#texpr (rvalue_type gctx v.v_type (Some v.v_name)) e1;

+ 8 - 0
src/generators/genlua.ml

@@ -574,7 +574,9 @@ and gen_cond ctx cond =
 
 and gen_loop ctx cond do_while e =
     let old_in_loop = ctx.in_loop in
+    let old_in_loop_try = ctx.in_loop_try in
     ctx.in_loop <- true;
+    ctx.in_loop_try <- false;
     let old_handle_continue = ctx.handle_continue in
     let will_continue = has_continue e in
     ctx.handle_continue <- has_continue e;
@@ -610,6 +612,7 @@ and gen_loop ctx cond do_while e =
     b();
     newline ctx;
     print ctx "end";
+    ctx.in_loop_try <- old_in_loop_try;
     ctx.in_loop <- old_in_loop;
     ctx.break_depth <- ctx.break_depth-1;
     ctx.handle_continue <- old_handle_continue;
@@ -1296,6 +1299,9 @@ and gen_value ctx e =
 and gen_tbinop ctx op e1 e2 =
     (match op, e1.eexpr, e2.eexpr with
      | Ast.OpAssign, TField(e3, (FInstance _ as ci)), TFunction f ->
+         let old = ctx.in_value, ctx.in_loop in
+         ctx.in_value <- None;
+         ctx.in_loop <- false;
          gen_expr ctx e1;
          spr ctx " = " ;
          let fn_args = List.map ident (List.map arg_name f.tf_args) in
@@ -1323,6 +1329,8 @@ and gen_tbinop ctx op e1 e2 =
               bend();
               newline ctx;
           | _ -> gen_value ctx e2);
+         ctx.in_value <- fst old;
+         ctx.in_loop <- snd old;
          spr ctx " end"
      | Ast.OpAssign, _, _ ->
          let iife_assign = ctx.iife_assign in

+ 2 - 0
src/generators/genphp7.ml

@@ -3891,6 +3891,8 @@ class class_builder ctx (cls:tclass) =
 					| Var { v_read = read; v_write = write } ->
 						if read = AccCall then getters := field.cf_name :: !getters;
 						if write = AccCall then setters := field.cf_name :: !setters;
+						if read = AccPrivateCall then getters := field.cf_name :: !getters;
+						if write = AccPrivateCall then setters := field.cf_name :: !setters;
 					| _ -> ()
 			in
 			List.iter collect cls.cl_ordered_fields;

+ 2 - 2
src/generators/genpy.ml

@@ -1718,7 +1718,7 @@ module Generator = struct
 			match cf.cf_kind with
 				| Var _ when not (is_physical_field cf) ->
 					()
-				| Var({v_read = AccCall}) ->
+				| Var({v_read = AccCall | AccPrivateCall}) ->
 					if Meta.has Meta.IsVar cf.cf_meta then
 						DynArray.add fields cf.cf_name
 					else
@@ -1922,7 +1922,7 @@ module Generator = struct
 			print ctx "    @staticmethod\n    def _hx_empty_init(_hx_o):";
 			let found_fields = ref false in
 			List.iter (fun cf -> match cf.cf_kind with
-					| Var ({v_read = AccCall}) ->
+					| Var ({v_read = AccCall | AccPrivateCall}) ->
 						()
 					| Var _ ->
 						found_fields := true;

+ 4 - 4
src/generators/genswf9.ml

@@ -2324,7 +2324,7 @@ let realize_required_accessors ctx cl =
 				if not (is_implemented_by_super ci) then begin
 					List.iter (fun cf ->
 						match cf.cf_kind with
-						| Var { v_read = (AccCall | AccNever) as read; v_write = (AccCall | AccNever) as write } ->
+						| Var { v_read = (AccCall | AccPrivateCall | AccNever) as read; v_write = (AccCall | AccPrivateCall | AccNever) as write } ->
 							begin try
 								let read', write', native = Hashtbl.find h cf.cf_name in
 								let read = if read = AccNever then read' else true in
@@ -2496,10 +2496,10 @@ let generate_class ctx c =
 				maybe_gen_instance_setter ctx c f acc alloc_slot
 			else
 				maybe_gen_static_setter ctx c f acc alloc_slot
-		| Var { v_read = (AccCall | AccNever) as read; v_write = (AccCall | AccNever) as write } when not (has_class_flag c CInterface) && not (Meta.has Meta.IsVar f.cf_meta) ->
+		| Var { v_read = (AccCall | AccPrivateCall | AccNever) as read; v_write = (AccCall | AccPrivateCall | AccNever) as write } when not (has_class_flag c CInterface) && not (Meta.has Meta.IsVar f.cf_meta) ->
 			(* if the accessor methods were defined in super classes, we still need to generate native getter/setter *)
 			let acc =
-				if read = AccCall then begin
+				if read = AccCall || read = AccPrivateCall then begin
 					try
 						begin
 						let tl = extract_param_types c.cl_params in
@@ -2524,7 +2524,7 @@ let generate_class ctx c =
 						acc
 				end else acc
 			in
-			if write = AccCall then begin
+			if write = AccCall || write = AccPrivateCall then begin
 				try
 					begin
 					let tl = extract_param_types c.cl_params in

+ 87 - 0
src/macro/eval/evalAtomic.ml

@@ -0,0 +1,87 @@
+open EvalValue
+open EvalEncode
+open EvalDecode
+open EvalExceptions
+open EvalHash
+
+let as_atomic_bool vthis = match vthis with
+	| VInstance {ikind = IAtomicBool i} -> i
+	| _ -> unexpected_value vthis "AtomicBool"
+let as_atomic_int vthis = match vthis with
+	| VInstance {ikind = IAtomicInt i} -> i
+	| _ -> unexpected_value vthis "AtomicInt"
+let as_atomic_object vthis = match vthis with
+	| VInstance {ikind = IAtomicObject i} -> i
+	| _ -> unexpected_value vthis "AtomicObject"
+
+let atomic_object_fields = [
+        "_hx_new", vfun1 (fun v -> encode_instance key_haxe_atomic_AtomicObject ~kind:(IAtomicObject (Atomic.make v)));
+        "load", vfun1 (fun v -> Atomic.get (as_atomic_object v));
+        "store", vfun2 (fun a v -> Atomic.set (as_atomic_object a) v; v);
+        "exchange", vfun2 (fun a v -> Atomic.exchange (as_atomic_object a) v);
+        "compareExchange", vfun3 (fun vthis a b ->
+            let vthis = as_atomic_object vthis in
+            let rec loop () = begin
+                let original = Atomic.get vthis in
+                let real_replacement = if EvalValue.equals original a then b else original in
+                if not (Atomic.compare_and_set vthis original real_replacement) then 
+                    loop ()
+                else
+                    original
+            end
+            in loop ());
+]
+
+let atomic_bool_fields = [
+        "_hx_new", vfun1 (fun v -> encode_instance key_haxe_atomic_AtomicBool ~kind:(IAtomicBool (Atomic.make (decode_bool v))));
+        "load", vfun1 (fun v -> vbool (Atomic.get (as_atomic_bool v)));
+        "store", vfun2 (fun a v -> Atomic.set (as_atomic_bool a) (decode_bool v); v);
+        "exchange", vfun2 (fun a v -> vbool (Atomic.exchange (as_atomic_bool a) (decode_bool v)));
+        "compareExchange", vfun3 (fun vthis a b ->
+            let vthis = as_atomic_bool vthis in
+            let a = decode_bool a and b = decode_bool b in
+            let rec loop () = begin
+                let original = Atomic.get vthis in
+                let real_replacement = if original = a then b else original in
+                if not (Atomic.compare_and_set vthis original real_replacement) then 
+                    loop ()
+                else
+                    vbool original
+            end
+            in loop ());
+]
+
+let fetch_update (this: 'a Atomic.t) (f: 'a -> 'a) =
+    let rec loop () = begin
+        let original = Atomic.get this in
+        let replacement = f original in
+        if not (Atomic.compare_and_set this original replacement) then 
+            loop ()
+        else
+            original
+    end
+    in loop ()
+
+let atomic_int_fields = [
+        "_hx_new", vfun1 (fun v -> encode_instance key_haxe_atomic_AtomicInt ~kind:(IAtomicInt (Atomic.make (decode_int v))));
+        "load", vfun1 (fun v -> vint (Atomic.get (as_atomic_int v)));
+        "store", vfun2 (fun a v -> Atomic.set (as_atomic_int a) (decode_int v); v);
+        "exchange", vfun2 (fun a v -> vint (Atomic.exchange (as_atomic_int a) (decode_int v)));
+        "compareExchange", vfun3 (fun vthis a b ->
+            let vthis = as_atomic_int vthis in
+            let a = decode_int a and b = decode_int b in
+            let rec loop () = begin
+                let original = Atomic.get vthis in
+                let real_replacement = if original = a then b else original in
+                if not (Atomic.compare_and_set vthis original real_replacement) then 
+                    loop ()
+                else
+                    vint original
+            end
+            in loop ());
+        "add", vfun2 (fun a v -> vint (Atomic.fetch_and_add (as_atomic_int a) (decode_int v)));
+        "sub", vfun2 (fun a v -> vint (Atomic.fetch_and_add (as_atomic_int a) (-(decode_int v))));
+        "and", vfun2 (fun a v -> let v = decode_int v in vint (fetch_update (as_atomic_int a) (fun orig -> orig land v)));
+        "or", vfun2 (fun a v -> let v = decode_int v in vint (fetch_update (as_atomic_int a) (fun orig -> orig lor v)));
+        "xor", vfun2 (fun a v -> let v = decode_int v in vint (fetch_update (as_atomic_int a) (fun orig -> orig lxor v)));
+]

+ 18 - 18
src/macro/eval/evalEmitter.ml

@@ -759,33 +759,33 @@ let process_arguments fl vl env =
 
 let create_function_noret ctx eci exec fl vl =
 	let env = push_environment ctx eci in
-	process_arguments fl vl env;
-	let v = exec env in
-	pop_environment ctx env;
-	v
+	Std.finally (fun () -> pop_environment ctx env) (fun () ->
+		process_arguments fl vl env;
+		exec env
+	) ()
 
 let create_function ctx eci exec fl vl =
 	let env = push_environment ctx eci in
-	process_arguments fl vl env;
-	let v = try exec env with Return v -> v in
-	pop_environment ctx env;
-	v
+	Std.finally (fun () -> pop_environment ctx env) (fun () ->
+		process_arguments fl vl env;
+		try exec env with Return v -> v
+	) ()
 
 let create_closure_noret ctx eci refs exec fl vl =
 	let env = push_environment ctx eci in
-	Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
-	process_arguments fl vl env;
-	let v = exec env in
-	pop_environment ctx env;
-	v
+	Std.finally (fun () -> pop_environment ctx env) (fun () ->
+		Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
+		process_arguments fl vl env;
+		exec env
+	) ()
 
 let create_closure refs ctx eci exec fl vl =
 	let env = push_environment ctx eci in
-	Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
-	process_arguments fl vl env;
-	let v = try exec env with Return v -> v in
-	pop_environment ctx env;
-	v
+	Std.finally (fun () -> pop_environment ctx env) (fun () ->
+		Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
+		process_arguments fl vl env;
+		try exec env with Return v -> v
+	) ()
 
 let emit_closure ctx mapping eci hasret exec fl env =
 	let refs = Array.map (fun (i,slot) -> i,emit_capture_read slot env) mapping in

+ 24 - 1
src/macro/eval/evalExceptions.ml

@@ -130,7 +130,30 @@ let catch_exceptions ctx ?(final=(fun() -> ())) f p =
 				| l when p' = null_pos -> l (* If the exception position is null_pos, we're "probably" in a built-in function. *)
 				| _ :: l -> l (* Otherwise, ignore topmost frame position. *)
 			in
-			get_exc_error_stack ctx stack
+			let def () =
+				get_exc_error_stack ctx stack
+			in
+			begin match v with
+			| VInstance vi when is v key_haxe_Exception ->
+				begin try
+					let vf = instance_field vi key_custom_stack in
+					begin match vf with
+					| VVector vv ->
+						Array.to_list vv |> List.map (fun v -> match v with
+							| VEnumValue {enpos = Some p} ->
+								p
+							| _ ->
+								die "" __LOC__
+						)
+					| _ ->
+						def();
+					end
+				with Not_found ->
+					def ()
+				end
+			| _ ->
+				def();
+			end
 		in
 
 		if is v key_haxe_macro_Error then begin

+ 4 - 0
src/macro/eval/evalHash.ml

@@ -48,6 +48,7 @@ let key_error = hash "error"
 let key_exception_message = hash "__exceptionMessage"
 let key_native_exception = hash "__nativeException"
 let key_native_stack = hash "__nativeStack"
+let key_custom_stack = hash "__customStack"
 let key_Array = hash "Array"
 let key_eval_Vector = hash "eval.Vector"
 let key_String = hash "String"
@@ -211,3 +212,6 @@ let key_address = hash "address"
 let key_netmask = hash "netmask"
 let key_previous = hash "previous"
 let key_current = hash "current"
+let key_haxe_atomic_AtomicBool = hash "haxe.atomic.AtomicBool" 
+let key_haxe_atomic_AtomicInt = hash "haxe.atomic.AtomicInt" 
+let key_haxe_atomic_AtomicObject = hash "haxe.atomic.AtomicObject" 

+ 3 - 3
src/macro/eval/evalStackTrace.ml

@@ -10,14 +10,14 @@ let make_stack envs =
 	List.iter (fun (pos,kind) ->
 		let file_pos s =
 			let line1,col1,_,_ = Lexer.get_pos_coords pos in
-			encode_enum_value key_haxe_StackItem 2 [|s;create_unknown pos.pfile;vint line1;vint col1|] None
+			encode_enum_value key_haxe_StackItem 2 [|s;create_unknown pos.pfile;vint line1;vint col1|] (Some pos)
 		in
 		match kind with
 		| EKLocalFunction i ->
-			let local_function = encode_enum_value key_haxe_StackItem 4 [|vint i|] None in
+			let local_function = encode_enum_value key_haxe_StackItem 4 [|vint i|] (Some pos) in
 			DynArray.add l (file_pos local_function);
 		| EKMethod(st,sf) ->
-			let local_function = encode_enum_value key_haxe_StackItem 3 [|create_unknown (rev_hash st); create_unknown (rev_hash sf)|] None in
+			let local_function = encode_enum_value key_haxe_StackItem 3 [|create_unknown (rev_hash st); create_unknown (rev_hash sf)|] (Some pos) in
 			DynArray.add l (file_pos local_function);
 		| EKMacro(st,sf) ->
 			()

+ 7 - 1
src/macro/eval/evalStdLib.ml

@@ -2709,6 +2709,8 @@ module StdSys = struct
 		)
 
 	let time = vfun0 (fun () -> vfloat (catch_unix_error Unix.gettimeofday()))
+
+	let timestamp_ms = vfun0 (fun () -> EvalIntegers.encode_haxe_i64_direct (* TODO: use vint64 once that works *) (Extc.timestamp_ms()))
 end
 
 module StdThread = struct
@@ -3727,6 +3729,7 @@ let init_standard_library builtins =
 		"stdout",StdSys.stdout;
 		"systemName",StdSys.systemName;
 		"time",StdSys.time;
+		"timestamp_ms",StdSys.timestamp_ms;
 	] [];
 	init_fields builtins (["eval";"vm"],"NativeThread") [
 		"delay",StdThread.delay;
@@ -3849,4 +3852,7 @@ let init_standard_library builtins =
 	init_fields builtins (["eval";"luv";"_Prepare"], "Prepare_Impl_") EvalLuv.prepare_fields [];
 	init_fields builtins (["eval";"luv";"_Check"], "Check_Impl_") EvalLuv.check_fields [];
 	init_fields builtins (["eval";"luv"], "Version") EvalLuv.version_fields [];
-	EvalSsl.init_fields init_fields builtins
+	EvalSsl.init_fields init_fields builtins;
+	init_fields builtins (["haxe";"atomic"; "_AtomicBool"], "AtomicBool_Impl_") EvalAtomic.atomic_bool_fields [];
+	init_fields builtins (["haxe";"atomic"; "_AtomicInt"], "AtomicInt_Impl_") EvalAtomic.atomic_int_fields [];
+	init_fields builtins (["haxe";"atomic"; "_AtomicObject"], "AtomicObject_Impl_") EvalAtomic.atomic_object_fields [];

+ 11 - 1
src/macro/eval/evalValue.ml

@@ -214,6 +214,9 @@ and vinstance_kind =
 	| IMbedtlsSsl of Mbedtls.mbedtls_ssl_context
 	| IMbedtlsX509Crt of Mbedtls.mbedtls_x509_crt
 	| INormal
+	| IAtomicBool of bool Atomic.t
+	| IAtomicInt of int Atomic.t
+	| IAtomicObject of value Atomic.t
 
 and vinstance = {
 	(* The fields of this instance. *)
@@ -238,7 +241,7 @@ and venum_value = {
 	eindex : int;
 	eargs : value array;
 	epath : int;
-	enpos : pos option;
+	mutable enpos : pos option;
 }
 
 and vthread = {
@@ -347,6 +350,7 @@ let vfield_closure v f = VFieldClosure(v,f)
 let vobject o = VObject o
 let vint i = VInt32 (Int32.of_int i)
 let vint32 i = VInt32 i
+let vint64 i = VInt64 i
 let vfloat f = VFloat f
 let venum_value e = VEnumValue e
 let vnative_string s = VNativeString s
@@ -356,3 +360,9 @@ let s_expr_pretty e = (Type.s_expr_pretty false "" false (Type.s_type (Type.prin
 let rec vresolve v = match v with
 	| VLazy f -> vresolve (Lazy.force f)
 	| _ -> v
+
+let associate_enum_value_pos ve p = match ve with
+	| VEnumValue ve ->
+		ve.enpos <- Some p
+	| _ ->
+		()

+ 10 - 1
src/macro/macroApi.ml

@@ -174,6 +174,8 @@ module type InterpApi = sig
 	val handle_decoding_error : (string -> unit) -> value -> Type.t -> (string * int) list
 
 	val get_api_call_pos : unit -> pos
+
+	val associate_enum_value_pos : value -> pos -> unit
 end
 
 let s_type_path = Globals.s_type_path
@@ -1124,6 +1126,7 @@ and encode_var_access a =
 		| AccInline	-> 5, []
 		| AccRequire (s,msg) -> 6, [encode_string s; null encode_string msg]
 		| AccCtor -> 7, []
+		| AccPrivateCall -> 8, []
 	) in
 	encode_enum IVarAccess tag pl
 
@@ -1450,6 +1453,7 @@ let decode_var_access v =
 	| 5, [] -> AccInline
 	| 6, [s1;s2] -> AccRequire(decode_string s1, opt decode_string s2)
 	| 7, [] -> AccCtor
+	| 8, [] -> AccPrivateCall
 	| _ -> raise Invalid_expr
 
 let decode_method_kind v =
@@ -2432,6 +2436,11 @@ let macro_api ccom get_api =
 		"set_hxb_writer_config", vfun1 (fun v ->
 			(get_api()).set_hxb_writer_config v;
 			vnull
-		)
+		);
+		"associate_enum_value_pos",vfun2 (fun ve vp ->
+			let p = decode_pos vp in
+			associate_enum_value_pos ve p;
+			vnull;
+		);
 	]
 end

+ 7 - 13
src/optimization/analyzer.ml

@@ -880,13 +880,7 @@ module Debug = struct
 	let dot_debug ctx c cf =
 		let g = ctx.graph in
 		let start_graph ?(graph_config=[]) suffix =
-			let ch = Path.create_file false suffix [] (get_dump_path ctx c cf) in
-			Printf.fprintf ch "digraph graphname {\n";
-			List.iter (fun s -> Printf.fprintf ch "%s;\n" s) graph_config;
-			ch,(fun () ->
-				Printf.fprintf ch "}\n";
-				close_out ch
-			)
+			DotGraph.start_graph ~graph_config (DotGraph.get_dump_path ctx.com c cf) suffix
 		in
 		let ch,f = start_graph "-cfg.dot" in
 		List.iter (fun bb -> dot_debug_node g ch [NILoopGroups;NIScopes;NIPhi;NIExpr] bb) g.g_nodes;
@@ -1118,12 +1112,12 @@ module Run = struct
 					print_endline (Type.s_expr_pretty true "" false (s_type (print_context())) e);
 					print_endline (Printf.sprintf "</%s>" s);
 				) (List.rev actx.debug_exprs);
-				Debug.dot_debug actx c cf;
-				print_endline (Printf.sprintf "dot graph written to %s" (String.concat "/" (Debug.get_dump_path actx c cf)));
+				Debug.dot_debug actx c.cl_path cf.cf_name;
+				print_endline (Printf.sprintf "dot graph written to %s" (String.concat "/" (DotGraph.get_dump_path actx.com c.cl_path cf.cf_name)));
 			in
 			let maybe_debug () = match config.debug_kind with
 				| DebugNone -> ()
-				| DebugDot -> Debug.dot_debug actx c cf;
+				| DebugDot -> Debug.dot_debug actx c.cl_path cf.cf_name;
 				| DebugFull -> debug()
 			in
 			begin try
@@ -1190,13 +1184,13 @@ module Run = struct
 		| TTypeDecl _ -> ()
 		| TAbstractDecl _ -> ()
 
-	let run_on_types scom pool types =
+	let run_on_types scom pool all_types new_types =
 		let config = get_base_config scom in
 		with_timer scom.timer_ctx config.detail_times None ["other"] (fun () ->
 			if config.optimize && config.purity_inference then
-				with_timer scom.timer_ctx config.detail_times None ["optimize";"purity-inference"] (fun () -> Purity.infer types);
+				with_timer scom.timer_ctx config.detail_times None ["optimize";"purity-inference"] (fun () -> Purity.infer all_types);
 			let exc_out = Atomic.make None in
-			Parallel.ParallelArray.iter pool (run_on_type scom exc_out pool config) types;
+			Parallel.ParallelArray.iter pool (run_on_type scom exc_out pool config) new_types;
 			check_exc_out exc_out
 		)
 end

+ 13 - 4
src/optimization/analyzerTexpr.ml

@@ -1006,10 +1006,19 @@ end
 
 module Cleanup = struct
 	let apply com e =
-		let if_or_op e e1 e2 e3 = match (Texpr.skip e1).eexpr,(Texpr.skip e3).eexpr with
-			| TUnop(Not,Prefix,e1),TConst (TBool true) -> optimize_binop {e with eexpr = TBinop(OpBoolOr,e1,e2)} OpBoolOr e1 e2
-			| _,TConst (TBool false) -> optimize_binop {e with eexpr = TBinop(OpBoolAnd,e1,e2)} OpBoolAnd e1 e2
-			| _,TBlock [] -> {e with eexpr = TIf(e1,e2,None)}
+		let if_or_op e e1 e2 e3 = match (Texpr.skip e1).eexpr,(Texpr.skip e2).eexpr,(Texpr.skip e3).eexpr with
+			| _,TReturn(Some b),TReturn(Some {eexpr = TConst (TBool false)}) ->
+				let binop = optimize_binop {e with eexpr = TBinop(OpBoolAnd,e1,b)} OpBoolAnd e1 b in
+				{e with eexpr = TReturn(Some binop)}
+			| TUnop(Not,Prefix,e1),TReturn(Some b),TReturn(Some {eexpr = TConst (TBool true)}) ->
+				let binop = optimize_binop {e with eexpr = TBinop(OpBoolOr,e1,b)} OpBoolOr e1 b in
+				{e with eexpr = TReturn(Some binop)}
+			| TUnop(Not,Prefix,e1),_,TConst (TBool true) ->
+				optimize_binop {e with eexpr = TBinop(OpBoolOr,e1,e2)} OpBoolOr e1 e2
+			| _,_,TConst (TBool false) ->
+				optimize_binop {e with eexpr = TBinop(OpBoolAnd,e1,e2)} OpBoolAnd e1 e2
+			| _,_,TBlock [] ->
+				{e with eexpr = TIf(e1,e2,None)}
 			| _ -> match (Texpr.skip e2).eexpr with
 				| TBlock [] ->
 					let e1' = mk (TUnop(Not,Prefix,e1)) e1.etype e1.epos in

+ 10 - 4
src/optimization/dce.ml

@@ -140,8 +140,8 @@ let rec keep_field dce cf c kind =
 			with Not_found -> false
 		in
 		match cf.cf_kind with
-		| Var { v_read = AccCall } -> check_accessor "get_"
-		| Var { v_write = AccCall } -> check_accessor "set_"
+		| Var { v_read = AccCall | AccPrivateCall } -> check_accessor "get_"
+		| Var { v_write = AccCall | AccPrivateCall } -> check_accessor "set_"
 		| _ -> false
 	end
 
@@ -747,11 +747,17 @@ let fix_accessors types =
 				| Var {v_read = AccCall; v_write = a} ->
 					let s = "get_" ^ cf.cf_name in
 					cf.cf_kind <- Var {v_read = if has_accessor c s stat then AccCall else AccNever; v_write = a}
+				| Var {v_read = AccPrivateCall; v_write = a} ->
+					let s = "get_" ^ cf.cf_name in
+					cf.cf_kind <- Var {v_read = if has_accessor c s stat then AccPrivateCall else AccNever; v_write = a}
 				| _ -> ());
 				(match cf.cf_kind with
 				| Var {v_write = AccCall; v_read = a} ->
 					let s = "set_" ^ cf.cf_name in
 					cf.cf_kind <- Var {v_write = if has_accessor c s stat then AccCall else AccNever; v_read = a}
+				| Var {v_write = AccPrivateCall; v_read = a} ->
+					let s = "set_" ^ cf.cf_name in
+					cf.cf_kind <- Var {v_write = if has_accessor c s stat then AccPrivateCall else AccNever; v_read = a}
 				| _ -> ())
 			in
 			List.iter (check_prop true) c.cl_ordered_statics;
@@ -863,7 +869,7 @@ let sweep dce types =
 					if not (Meta.has Meta.Accessor cf.cf_meta) then cf.cf_meta <- (Meta.Accessor,[],mk_zero_range_pos c.cl_pos) :: cf.cf_meta
 				in
 				begin match cf.cf_kind with
-				| Var {v_read = AccCall} ->
+				| Var {v_read = AccCall | AccPrivateCall} ->
 					begin try
 						add_accessor_metadata (PMap.find ("get_" ^ cf.cf_name) (if stat then c.cl_statics else c.cl_fields))
 					with Not_found ->
@@ -873,7 +879,7 @@ let sweep dce types =
 					()
 				end;
 				begin match cf.cf_kind with
-				| Var {v_write = AccCall} ->
+				| Var {v_write = AccCall | AccPrivateCall} ->
 					begin try
 						add_accessor_metadata (PMap.find ("set_" ^ cf.cf_name) (if stat then c.cl_statics else c.cl_fields))
 					with Not_found ->

+ 1 - 1
src/optimization/inline.ml

@@ -268,7 +268,7 @@ let inline_config cls_opt cf call_args return_type =
 let inline_metadata e meta =
 	let inline_meta e meta = match meta with
 		| Meta.Pure,[EConst(Ident "inferredPure"),_],_ -> e
-		| (Meta.Deprecated | Meta.Pure),_,_ -> mk (TMeta(meta,e)) e.etype e.epos
+		| (Meta.Deprecated | Meta.Pure | Meta.NullSafety),_,_ -> mk (TMeta(meta,e)) e.etype e.epos
 		| _ -> e
 	in
 	List.fold_left inline_meta e meta

+ 20 - 17
src/optimization/inlineConstructors.ml

@@ -232,23 +232,26 @@ let inline_constructors (scom : SafeCom.t) original_e =
 		The id is incremented each time and is used later in the final_map phase to identify the correct inline_object.
 	*)
 	let rec mark_ctors ?(force_inline=false) e : texpr =
-		let is_meta_inline = match e.eexpr with (TMeta((Meta.Inline,_,_),e)) -> true | _ -> false in
-		let e = Type.map_expr (mark_ctors ~force_inline:is_meta_inline) e in
-		let mark() =
-			incr curr_io_id;
-			let id_expr = (EConst(Int (string_of_int !curr_io_id, None)), e.epos) in
-			let meta = (Meta.InlineObject, [id_expr], e.epos) in
-			mk (TMeta(meta, e)) e.etype e.epos
-		in
-		match e.eexpr, force_inline with
-			| TObjectDecl _, _
-			| TArrayDecl _, _
-			| TNew _, true ->
-				mark()
-			| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction _})} as cf)} as c,_,_), _ ->
-				if needs_inline scom (Some c) cf then mark()
-				else e
-			| _ -> e
+		match e.eexpr with
+			| TMeta((Meta.InlineConstructorArgument _,_,_),_) -> e
+			| _ ->
+				let is_meta_inline = match e.eexpr with (TMeta((Meta.Inline,_,_),e)) -> true | _ -> false in
+				let e = Type.map_expr (mark_ctors ~force_inline:is_meta_inline) e in
+				let mark() =
+					incr curr_io_id;
+					let id_expr = (EConst(Int (string_of_int !curr_io_id, None)), e.epos) in
+					let meta = (Meta.InlineObject, [id_expr], e.epos) in
+					mk (TMeta(meta, e)) e.etype e.epos
+				in
+				match e.eexpr, force_inline with
+					| TObjectDecl _, _
+					| TArrayDecl _, _
+					| TNew _, true ->
+						mark()
+					| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction _})} as cf)} as c,_,_), _ ->
+						if needs_inline scom (Some c) cf then mark()
+						else e
+					| _ -> e
 	in
 
 	(*

+ 20 - 2
src/prebuild.ml

@@ -115,6 +115,7 @@ type parsed_define = {
 	d_deprecated : string option;
 	d_deprecated_define : string option;
 	d_default : string option;
+	d_signature_neutral : bool option;
 }
 let parse_define json =
 	let fields = match json with
@@ -131,6 +132,7 @@ let parse_define json =
 		d_deprecated = get_optional_field2 "deprecated" as_string fields;
 		d_deprecated_define = get_optional_field2 "deprecatedDefine" as_string fields;
 		d_default = get_optional_field2 "default" as_string fields;
+		d_signature_neutral = get_optional_field2 "signatureNeutral" as_bool fields;
 	}
 
 let parse_meta json =
@@ -204,6 +206,7 @@ let gen_option f = function
 let gen_define_info defines =
 	let deprecations = DynArray.create() in
 	let default_values = DynArray.create() in
+	let sig_neutral = DynArray.create() in
 	let define_str = List.map (function
 		def ->
 			let platforms_str = gen_platforms def.d_platforms in
@@ -233,12 +236,21 @@ let gen_define_info defines =
 					DynArray.add default_values (Printf.sprintf "\t(%S,%S)" define x);
 					[Printf.sprintf "DefaultValue(%s)" quoted]
 			in
+			(match def.d_signature_neutral with
+				| Some true ->
+					DynArray.add sig_neutral (Printf.sprintf "| %S" (convert_define define));
+					begin match def.d_deprecated_define with
+					| None -> ()
+					| Some s -> DynArray.add sig_neutral (Printf.sprintf "| %S" (convert_define s))
+					end
+				| _ -> ());
 			"\t| " ^ def.d_name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" def.d_doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str @ deprecated @ default)) ^ "])"
 	) defines in
 	(
 		String.concat "\n" define_str,
 		String.concat "\n" (DynArray.to_list deprecations),
-		String.concat ";\n" (DynArray.to_list default_values)
+		String.concat ";\n" (DynArray.to_list default_values),
+		String.concat " " (DynArray.to_list sig_neutral)
 	)
 
 let gen_meta_type metas =
@@ -379,10 +391,16 @@ match Array.to_list (Sys.argv) with
 		Printf.printf "type strict_defined =\n";
 		Printf.printf "%s" (gen_define_type defines);
 		Printf.printf "\n\t| Last\n\t| Custom of string\n\n";
-		let infos,deprecations,default_values = gen_define_info defines in
+		let infos,deprecations,default_values,sig_neutral = gen_define_info defines in
 		Printf.printf "let infos = function\n";
 		Printf.printf "%s" infos;
 		Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n";
+		if sig_neutral = "" then
+			Printf.printf "let is_signature_neutral _ = false\n"
+		else begin
+			Printf.printf "let is_signature_neutral = function\n";
+			Printf.printf "\t%s -> true\n\t| _ -> false\n" sig_neutral;
+		end;
 		Printf.printf "\nlet deprecated_defines = [\n%s\n]\n" deprecations;
 		Printf.printf "\nlet default_values = [\n%s\n]\n" default_values;
 	| [_; "meta"; meta_path]->

+ 1 - 0
src/syntax/grammar.ml

@@ -85,6 +85,7 @@ let lower_ident_or_macro = function%parser
 
 let property_ident = function%parser
 	| [ ident as i ] -> i
+	| [ (Kwd Private,p1); (Const (Ident i),p2) ] -> "private " ^ i, punion p1 p2
 	| [ (Kwd Dynamic,p) ] -> "dynamic",p
 	| [ (Kwd Default,p) ] -> "default",p
 	| [ (Kwd Null,p) ] -> "null",p

+ 4 - 13
src/syntax/lexer.ml

@@ -270,15 +270,13 @@ let resolve_file_pos file =
 		f
 
 let find_file file =
-	try
-		ThreadSafeHashtbl.find all_files file
-	with Not_found ->
+	ThreadSafeHashtbl.find_or_add all_files file (fun () ->
 		try
-			let f = resolve_file_pos file in
-			ThreadSafeHashtbl.add all_files file f;
-			f
+			(* TODO: It's actually stupid to block the entire Hashtbl while we're reading a file... *)
+			resolve_file_pos file
 		with Sys_error _ ->
 			make_file file
+	)
 
 let find_pos p =
 	find_line p.pmin (find_file p.pfile)
@@ -287,13 +285,6 @@ let get_error_line p =
 	let l, _ = find_pos p in
 	l
 
-let get_error_line_if_exists p =
-	try
-		let file = ThreadSafeHashtbl.find all_files p.pfile in
-		fst (find_line p.pmin file)
-	with Not_found ->
-		0
-
 let get_pos_coords p =
 	let file = find_file p.pfile in
 	let l1, p1 = find_line p.pmin file in

+ 0 - 1
src/syntax/parserConfig.ml

@@ -1,6 +1,5 @@
 open Globals
 open Common
-open DisplayPosition
 
 let default_config defines =
 	Parser.create_config defines false false DMNone false None

+ 2 - 2
src/typing/callUnification.ml

@@ -625,7 +625,7 @@ object(self)
 			end;
 		| Var v ->
 			begin match (if is_set then v.v_write else v.v_read) with
-			| AccCall ->
+			| AccCall | AccPrivateCall ->
 				self#accessor_call fa el_typed el
 			| _ ->
 				self#expr_call (FieldAccess.get_field_expr fa FCall) el_typed el
@@ -664,4 +664,4 @@ let make_static_call_better ctx c cf tl el t p =
 	let e1 = Builder.make_static_this c p in
 	let fa = FieldAccess.create e1 cf fh false p in
 	let fcc = unify_field_call ctx fa el [] p false in
-	fcc.fc_data()
+	fcc.fc_data()

+ 1 - 1
src/typing/fieldAccess.ml

@@ -93,7 +93,7 @@ let get_field_expr fa mode =
 let find_accessor_for_field host cf t mode = match cf.cf_kind with
 	| Var v ->
 		begin match (match mode with MSet _ -> v.v_write | _ -> v.v_read) with
-			| AccCall ->
+			| AccCall | AccPrivateCall ->
 				let name = (match mode with MSet _ -> "set_" | _ -> "get_") ^ cf.cf_name in
 				let forward cf_acc new_host =
 					(cf_acc,new_host)

+ 34 - 7
src/typing/fields.ml

@@ -163,26 +163,53 @@ let field_access ctx mode f fh e pfield =
 			AKUsingField sea
 		end;
 	| Var v ->
+		let is_prop_access access =
+			match access with
+				| AccCall | AccPrivateCall -> ctx.e.bypass_accessor = 0
+				| _ -> false
+		in
+		let check_field_with_mode c stat =
+			begin match mode with
+				| MGet when is_prop_access v.v_read ->
+					let can = can_access ctx c f ~check_prop:true ~is_setter:false stat in
+					if not can then
+						raise_typing_error "This property cannot be accessed for reading" pfield
+				| MSet _ when is_prop_access v.v_write ->
+					let can = can_access ctx c f ~check_prop:true ~is_setter:true stat in
+					if not can then
+						raise_typing_error "This property cannot be accessed for writing" pfield
+				| _ -> check_field_access ctx c f stat pfield
+			end
+		in
 		begin match fh with
 		| FHStatic c | FHAbstract(_,_,c) ->
-			check_field_access ctx c f true pfield
+			check_field_with_mode c true;
 		| FHInstance _ ->
 			begin match follow e.etype with
 			| TInst(c,_) ->
-				check_field_access ctx c f false pfield
+				check_field_with_mode c false;
 			| _ ->
 				()
 			end;
 			if e.eexpr = TConst TSuper then begin match mode with
-				| MGet | MCall _ when v.v_read = AccCall ->
+				| MGet | MCall _ when v.v_read = AccCall || v.v_read = AccPrivateCall ->
 					()
-				| MSet _ when v.v_write = AccCall ->
+				| MSet _ when v.v_write = AccCall || v.v_write = AccPrivateCall ->
 					()
 				| _ ->
 					display_error ctx.com "Normal variables cannot be accessed with 'super', use 'this' instead" pfield;
 			end;
 		| FHAnon ->
-			()
+			let is_private_access access =
+				access = AccPrivateCall && not (Meta.has Meta.PrivateAccess ctx.f.meta) && ctx.e.bypass_accessor = 0
+			in
+			begin match mode with
+				| MGet when is_private_access v.v_read ->
+					raise_typing_error "This property cannot be accessed for reading" pfield
+				| MSet _ when is_private_access v.v_write ->
+					raise_typing_error "This property cannot be accessed for writing" pfield
+				| _ -> ()
+			end;
 		end;
 		let normal inline =
 			AKField (make_access inline)
@@ -203,9 +230,9 @@ let field_access ctx mode f fh e pfield =
 				if ctx.f.untyped then normal false else normal_failure())
 		| AccNormal | AccNo ->
 			normal false
-		| AccCall when (not ctx.allow_transform) || (ctx.f.in_display && DisplayPosition.display_position#enclosed_in pfull) ->
+		| AccCall | AccPrivateCall when (not ctx.allow_transform) || (ctx.f.in_display && DisplayPosition.display_position#enclosed_in pfull) ->
 			normal false
-		| AccCall ->
+		| AccCall | AccPrivateCall ->
 			let m = (match mode with MSet _ -> "set_" | _ -> "get_") ^ f.cf_name in
 			let bypass_accessor =
 				(

+ 7 - 1
src/typing/generic.ml

@@ -121,7 +121,8 @@ let generic_substitute_expr gctx e =
 	in
 	let rec build_expr e =
 		let e = match e.eexpr with
-		| TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) ->
+		| TField(e1, (FInstance({cl_kind = KGeneric} as c,tl,cf) as fa_orig)) 
+		| TField(e1, (FClosure(Some ({cl_kind = KGeneric} as c, tl), cf) as fa_orig)) ->
 			let info = gctx.ctx.g.get_build_info gctx.ctx (TClassDecl c) gctx.p in
 			let t = info.build_apply (List.map (generic_substitute_type' gctx true) tl) in
 			begin match follow t with
@@ -134,6 +135,11 @@ let generic_substitute_expr gctx e =
 				with Not_found ->
 					raise_typing_error (Printf.sprintf "Type %s has no field %s (possible typing order issue)" (s_type (print_context()) t) cf.cf_name) e.epos
 				in
+				(* preserve FClosure *)
+				let fa = match fa_orig, fa with
+					| FClosure _, FInstance(c,tl,cf) -> FClosure(Some(c,tl),cf)
+					| _ -> fa
+				in
 				build_expr {e with eexpr = TField(e1,fa)}
 			end;
 		| TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta ->

+ 11 - 12
src/typing/macroContext.ml

@@ -57,15 +57,15 @@ let safe_decode com v expected t p f =
 			raise_decode_error (Printf.sprintf "Expected %s but got %s" expected (Interp.value_string v))
 
 
-let macro_timer timer_ctx level label identifier f arg =
-	let id = Timer.determine_id level ["macro"] [label] identifier in
+let macro_timer timer_ctx level s identifier f arg =
+	let id = Timer.determine_id level ["macro"] s identifier in
 	Timer.time timer_ctx id f arg
 
 let typing_timer ctx need_type f =
 	let t = Timer.start_timer ctx.com.timer_ctx ["typing"] in
 	let ctx = if need_type && ctx.pass < PTypeField then begin
 		enter_field_typing_pass ctx.g ("typing_timer",[]);
-		TyperManager.clone_for_expr ctx ctx.e.curfun false
+		TyperManager.clone_for_expr ctx ctx.e.curfun FunFunction
 	end else
 		ctx
 	in
@@ -141,22 +141,22 @@ let make_macro_com_api com mcom p =
 		);
 		after_init_macros = (fun f ->
 			com.callbacks#add_after_init_macros (fun () ->
-				macro_timer com.timer_ctx timer_level "afterInitMacros" None f ();
+				macro_timer com.timer_ctx timer_level ["afterInitMacros"] None f ();
 			)
 		);
 		after_typing = (fun f ->
 			com.callbacks#add_after_typing (fun tl ->
-				macro_timer com.timer_ctx timer_level "afterTyping" None f tl;
+				macro_timer com.timer_ctx timer_level ["afterTyping"] None f tl;
 			)
 		);
 		on_generate = (fun f b ->
 			(if b then com.callbacks#add_before_save else com.callbacks#add_after_save) (fun() ->
-				macro_timer com.timer_ctx timer_level "onGenerate"None f (List.map type_of_module_type com.types);
+				macro_timer com.timer_ctx timer_level ["onGenerate"] None f (List.map type_of_module_type com.types);
 			)
 		);
 		after_generate = (fun f ->
 			com.callbacks#add_after_generation (fun() ->
-				macro_timer com.timer_ctx timer_level "afterGenerate" None f ();
+				macro_timer com.timer_ctx timer_level ["afterGenerate"] None f ();
 			)
 		);
 		on_type_not_found = (fun f ->
@@ -653,12 +653,11 @@ and flush_macro_context mint mctx =
 			if apply_native then Native.apply_native_paths t
 		in
 		let scom = SafeCom.of_typer mctx in
-		let cv_wrapper_impl = CapturedVars.get_wrapper_implementation mctx.com in
 		let expr_filters = [
 			"handle_abstract_casts",AbstractCast.handle_abstract_casts;
 			"local_statics",LocalStatic.run;
 			"Exceptions",(fun _ -> Exceptions.filter ectx);
-			"captured_vars",(fun scom -> CapturedVars.captured_vars scom cv_wrapper_impl);
+			"captured_vars",(fun scom -> CapturedVars.captured_vars scom mctx.com.local_wrapper);
 		] in
 		let type_filters = [
 			(fun _ -> FiltersCommon.remove_generic_base);
@@ -677,7 +676,7 @@ and flush_macro_context mint mctx =
 		with Error err -> raise (Fatal_error err));
 	in
 	let timer_level = Timer.level_from_define mctx.com.defines Define.MacroTimes in
-	macro_timer mctx.com.timer_ctx timer_level "flush" None f ()
+	macro_timer mctx.com.timer_ctx timer_level ["flush"] None f ()
 
 let create_macro_interp api mctx =
 	let com2 = mctx.com in
@@ -810,7 +809,7 @@ let load_macro'' com mctx display cpath fname p =
 			mctx.com.cached_macros#add (cpath,fname) meth;
 			meth
 		in
-		macro_timer com.timer_ctx timer_level "typing" (Some (s_type_path cpath ^ "." ^ fname)) f ()
+		macro_timer com.timer_ctx timer_level ["typing";s_type_path cpath ^ "." ^ fname] None f ()
 
 let load_macro' ctx display cpath f p =
 	(* TODO: The only reason this nonsense is here is because this is the signature
@@ -823,7 +822,7 @@ let do_call_macro com api cpath name args p =
 	incr stats.s_macros_called;
 	let timer_level = Timer.level_from_define com.defines Define.MacroTimes in
 	let f = Interp.call_path (Interp.get_ctx()) ((fst cpath) @ [snd cpath]) name args in
-	let r = macro_timer com.timer_ctx timer_level "execution" (Some (s_type_path cpath ^ "." ^ name)) f api in
+	let r = macro_timer com.timer_ctx timer_level ["execution";s_type_path cpath ^ "." ^ name] None f api in
 	if com.verbose then Common.log com ("Exiting macro " ^ s_type_path cpath ^ "." ^ name);
 	r
 

+ 164 - 53
src/typing/nullSafety.ml

@@ -367,9 +367,26 @@ let rec process_condition mode condition (is_nullable_expr:texpr->bool) callback
 		if to_nulls then nulls := expr :: !nulls
 		else not_nulls := expr :: !not_nulls
 	in
+	let remove expr =
+		let expr = reveal_expr expr in
+		let subj = get_subject mode expr in
+		nulls := List.filter (fun e ->
+			let e_subj = get_subject mode (reveal_expr e) in
+			e_subj <> subj
+		) !nulls;
+		not_nulls := List.filter (fun e ->
+			let e_subj = get_subject mode (reveal_expr e) in
+			e_subj <> subj
+		) !not_nulls;
+	in
 	let rec traverse positive e =
 		match e.eexpr with
 			| TUnop (Not, Prefix, e) -> traverse (not positive) e
+			| TBinop (OpAssign, checked_expr, e) when is_suitable mode checked_expr && (is_nullable_expr e) ->
+				(* remove expr from both list if there is `e = nullable` in condition *)
+				remove checked_expr
+			| TBlock exprs ->
+				List.iter (fun e -> traverse positive e) exprs
 			| TBinop (OpEq, { eexpr = TConst TNull }, checked_expr) when is_suitable mode checked_expr ->
 				add positive checked_expr
 			| TBinop (OpEq, checked_expr, { eexpr = TConst TNull }) when is_suitable mode checked_expr ->
@@ -834,12 +851,13 @@ class local_safety (mode:safety_mode) =
 				| TWhile (condition, body, NormalWhile) ->
 					condition_callback condition;
 					let (nulls, not_nulls) = process_condition mode condition is_nullable_expr (fun _ -> ()) in
+					let original_safe = self#get_safe_locals_copy in
 					(** execute `body` with known not-null variables *)
 					List.iter self#get_current_scope#add_to_safety not_nulls;
 					body_callback
 						(fun () -> List.iter self#get_current_scope#add_to_safety not_nulls)
 						body;
-					List.iter self#get_current_scope#remove_from_safety not_nulls;
+					self#get_current_scope#filter_safety original_safe;
 				| _ -> fail ~msg:"Expected TWhile" expr.epos __POS__
 		(**
 			Should be called for bodies of loops (for, while)
@@ -955,18 +973,46 @@ class local_safety (mode:safety_mode) =
 		*)
 		method process_and left_expr right_expr is_nullable_expr (callback:texpr->unit) =
 			callback left_expr;
-			let (_, not_nulls) = process_condition mode left_expr is_nullable_expr (fun e -> ()) in
-			List.iter self#get_current_scope#add_to_safety not_nulls;
+			let original_safe = self#get_safe_locals_copy in
+			(* save not_nulls for `a != null && a > 0` *)
+			let (_, not_nulls) = process_condition mode left_expr is_nullable_expr (fun _ -> ()) in
+			(* create temp scope for right_expr *)
+			let temp_scope = new safety_scope mode STNormal (Hashtbl.copy original_safe) (Hashtbl.create 10) in
+			List.iter temp_scope#add_to_safety not_nulls;
+			scopes <- temp_scope :: scopes;
 			callback right_expr;
-			List.iter self#get_current_scope#remove_from_safety not_nulls
+			self#scope_closed;
+
+			let safe_after_rhs = temp_scope#get_safe_locals in
+			let final_safe = Hashtbl.create (Hashtbl.length original_safe) in
+			Hashtbl.iter (fun subj e ->
+				if Hashtbl.mem original_safe subj && Hashtbl.mem safe_after_rhs subj then
+					Hashtbl.replace final_safe subj e
+			) original_safe;
+
+			self#get_current_scope#reset_to final_safe;
 		(**
 			Handle boolean OR outside of `if` condition.
 		*)
 		method process_or left_expr right_expr is_nullable_expr (callback:texpr->unit) =
+			let original_safe = self#get_safe_locals_copy in
+			(* save nulls for `a == null || a > 0` *)
 			let (nulls, _) = process_condition mode left_expr is_nullable_expr callback in
-			List.iter self#get_current_scope#add_to_safety nulls;
+			(* create temp scope for right_expr *)
+			let temp_scope = new safety_scope mode STNormal (Hashtbl.copy original_safe) (Hashtbl.create 10) in
+			List.iter temp_scope#add_to_safety nulls;
+			scopes <- temp_scope :: scopes;
 			callback right_expr;
-			List.iter self#get_current_scope#remove_from_safety nulls
+			self#scope_closed;
+
+			let safe_after_rhs = temp_scope#get_safe_locals in
+			let final_safe = Hashtbl.create (Hashtbl.length original_safe) in
+			Hashtbl.iter (fun subj e ->
+				if Hashtbl.mem original_safe subj && Hashtbl.mem safe_after_rhs subj then
+					Hashtbl.replace final_safe subj e
+			) original_safe;
+
+			self#get_current_scope#reset_to final_safe;
 		(**
 			Remove subject from the safety list if a nullable value is assigned or if an object with safe field is reassigned.
 		*)
@@ -1072,8 +1118,10 @@ class expr_checker mode immediate_execution report =
 					is_nullable_type e.etype && not (local_safety#is_safe e)
 		(**
 			Check if `expr` can be passed to a place where `to_type` is expected.
-			This method has side effect: it logs an error if `expr` has a type parameter incompatible with the type parameter of `to_type`.
-			E.g.: `Array<Null<String>>` vs `Array<String>` returns `true`, but also adds a compilation error.
+			This method has side effects:
+			- it logs an error if `expr` has a type parameter incompatible with the type parameter of `to_type`.
+				E.g.: `Array<Null<String>>` vs `Array<String>` returns `true`, but also adds a compilation error.
+			- it logs an error on anon structure field nullability mismatch to report specific field error and returns `true`.
 		*)
 		method can_pass_expr expr to_type p =
 			let try_unify expr to_type =
@@ -1093,28 +1141,26 @@ class expr_checker mode immediate_execution report =
 							fail ~msg:"Null safety unification failure" expr.epos __POS__
 				end
 			in
+			let check_anon_fields fields to_type =
+				List.fold_left (fun acc ((name, _, _), field_expr) ->
+					try
+						let field_to_type = PMap.find name to_type.a_fields in
+						let field_pos = field_expr.epos in
+						if not (self#can_pass_expr field_expr field_to_type.cf_type field_pos) then
+							self#error "Cannot assign nullable value here." [field_pos];
+						acc && true
+					with Not_found -> false) true fields
+			in
 			match expr.eexpr, to_type with
 				| TLocal v, _ when contains_unsafe_meta v.v_meta -> true
 				| TObjectDecl fields, TAbstract ({ a_path = ([],"Null") }, [TAnon to_type])
 				| TObjectDecl fields, TAnon to_type ->
-					List.for_all
-						(fun ((name, _, _), field_expr) ->
-							try
-								let field_to_type = PMap.find name to_type.a_fields in
-								self#can_pass_expr field_expr field_to_type.cf_type p
-							with Not_found -> false)
-						fields
+					check_anon_fields fields to_type
 				| TObjectDecl fields, TAbstract ({ a_path = ([],"Null") }, [TType (t,tl)])
 				| TObjectDecl fields, TType (t,tl) ->
 					(match follow_without_null t.t_type with
 							| TAnon to_type ->
-								List.for_all
-									(fun ((name, _, _), field_expr) ->
-										try
-											let field_to_type = PMap.find name to_type.a_fields in
-											self#can_pass_expr field_expr field_to_type.cf_type p
-										with Not_found -> false)
-									fields
+								check_anon_fields fields to_type
 							| _ -> try_unify expr to_type
 					)
 				| _, _ -> try_unify expr to_type
@@ -1488,7 +1534,7 @@ class expr_checker mode immediate_execution report =
 			traverse 0 args types meta
 	end
 
-class class_checker cls immediate_execution report =
+class class_checker cls immediate_execution report (main_expr : texpr option) =
 	let cls_meta = cls.cl_meta @ (match cls.cl_kind with KAbstractImpl a -> a.a_meta | _ -> []) in
 	object (self)
 			val is_safe_class = (safety_enabled cls_meta)
@@ -1546,7 +1592,9 @@ class class_checker cls immediate_execution report =
 										| _ -> ()
 					in
 					if read_access = AccCall then check_accessor "get_";
-					if write_access = AccCall then check_accessor "set_"
+					if write_access = AccCall then check_accessor "set_";
+					if read_access = AccPrivateCall then check_accessor "get_";
+					if write_access = AccPrivateCall then check_accessor "set_";
 				| _ -> ()
 		(**
 			Get safety mode for the current class
@@ -1570,34 +1618,84 @@ class class_checker cls immediate_execution report =
 		*)
 		method private is_in_safety field =
 			(is_safe_class && not (contains_unsafe_meta field.cf_meta)) || safety_enabled field.cf_meta
+		(**
+			Extract `tf_expr` from `com.main.main_expr` if this expr in current class
+		*)
+		method private get_main_tf_expr (main_expr : texpr option) =
+			match main_expr with
+				| Some main_expr ->
+					begin match main_expr.eexpr with
+						| TCall ({ eexpr = TField (_, FStatic (cl, field))}, _) when cl == cls ->
+							begin match field.cf_expr with
+								| Some ({ eexpr = TFunction { tf_expr = e } }) ->
+									Some e
+								| _ -> None
+							end
+						| _ -> None
+					end
+				| None -> None
 		(**
 			Check `var` fields are initialized properly
 		*)
 		method check_var_fields =
 			let check_field is_static field =
 				validate_safety_meta report field.cf_meta;
-				if should_be_initialized field then
-					if not (is_nullable_type field.cf_type) && self#is_in_safety field then
-						match field.cf_expr with
-							| None ->
-								if is_static then
-									checker#error
-										("Field \"" ^ field.cf_name ^ "\" is not nullable thus should have an initial value.")
-										[field.cf_pos]
-							| Some e ->
-								if not (checker#can_pass_expr e field.cf_type e.epos) then
-									checker#error ("Cannot set nullable initial value for not-nullable field \"" ^ field.cf_name ^ "\".") [field.cf_pos]
+				if
+					should_be_initialized field
+					&& not (is_nullable_type field.cf_type)
+					&& self#is_in_safety field
+				then
+					match field.cf_expr with
+						| Some e ->
+							if not (checker#can_pass_expr e field.cf_type e.epos) then
+								checker#error
+								("Cannot set nullable initial value for not-nullable field \"" ^ field.cf_name ^ "\".") [field.cf_pos]
+						| None -> ()
 			in
 			List.iter (check_field false) cls.cl_ordered_fields;
 			List.iter (check_field true) cls.cl_ordered_statics;
+
+			self#check_statics_initialization ();
 			self#check_fields_initialization_in_constructor ()
+
+		method private check_statics_initialization () =
+			let fields_to_initialize = Hashtbl.create 20 in
+			List.iter
+				(fun f ->
+					if
+						should_be_initialized f
+						&& not (is_nullable_type f.cf_type)
+						&& not (contains_unsafe_meta f.cf_meta)
+					then
+						match f.cf_expr with
+							| Some _ -> ()
+							| None -> Hashtbl.add fields_to_initialize f.cf_name f
+				)
+				cls.cl_ordered_statics;
+
+			begin match TClass.get_cl_init cls with
+				| Some init_expr ->
+					ignore (self#check_fields_initialization fields_to_initialize init_expr true);
+				| None -> ()
+			end;
+			let main_tf_expr = self#get_main_tf_expr main_expr in
+			(match main_tf_expr with
+				| Some tf_expr ->
+					ignore (self#check_fields_initialization fields_to_initialize tf_expr true);
+				| _ -> ()
+			);
+			Hashtbl.iter
+				(fun name field ->
+					checker#error
+						("Field \"" ^ name ^ "\" is not nullable thus should have an initial value.")
+						[field.cf_pos]
+				)
+				fields_to_initialize
 		(**
 			Check instance fields without initial values are properly initialized in constructor
 		*)
 		method private check_fields_initialization_in_constructor () =
-			let fields_to_initialize = Hashtbl.create 20
-			(* Compiler-autogenerated local vars for transfering `this` to local functions *)
-			and this_vars = Hashtbl.create 5 in
+			let fields_to_initialize = Hashtbl.create 20 in
 			List.iter
 				(fun f ->
 					if
@@ -1610,10 +1708,30 @@ class class_checker cls immediate_execution report =
 							| None -> Hashtbl.add fields_to_initialize f.cf_name f
 				)
 				cls.cl_ordered_fields;
+
+			(match cls.cl_constructor with
+				| Some { cf_expr = Some { eexpr = TFunction { tf_expr = e } } } ->
+					ignore (self#check_fields_initialization fields_to_initialize e false);
+				| _ -> ()
+			);
+			Hashtbl.iter
+				(fun name field ->
+					checker#error
+						("Field \"" ^ name ^ "\" is not nullable thus should have an initial value or should be initialized in constructor.")
+						[field.cf_pos]
+				)
+				fields_to_initialize
+
+		method private check_fields_initialization fields_to_initialize tf_expr is_static =
+			(* Compiler-autogenerated local vars for transfering `this` to local functions *)
+			let this_vars = Hashtbl.create 5 in
 			let rec check_unsafe_usage init_list safety_enabled e =
 				if Hashtbl.length init_list > 0 then
 					match e.eexpr with
-						| TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) ->
+						| TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) when not is_static ->
+							if Hashtbl.mem init_list field.cf_name then
+								checker#error ("Cannot use field " ^ field.cf_name ^ " until initialization.") [e.epos]
+						| TField (_, FStatic (_, field)) when is_static ->
 							if Hashtbl.mem init_list field.cf_name then
 								checker#error ("Cannot use field " ^ field.cf_name ^ " until initialization.") [e.epos]
 						| TField ({ eexpr = TConst TThis }, FClosure (_, field)) ->
@@ -1634,7 +1752,11 @@ class class_checker cls immediate_execution report =
 			in
 			let rec traverse init_list e =
 				(match e.eexpr with
-					| TBinop (OpAssign, { eexpr = TField ({ eexpr = TConst TThis }, FInstance (_, _, f)) }, right_expr) ->
+					| TBinop (OpAssign, { eexpr = TField ({ eexpr = TConst TThis }, FInstance (_, _, f)) }, right_expr)
+						when not is_static ->
+						Hashtbl.remove init_list f.cf_name;
+						ignore (traverse init_list right_expr)
+					| TBinop (OpAssign, { eexpr = TField(_, FStatic(_, f)) }, right_expr) when is_static ->
 						Hashtbl.remove init_list f.cf_name;
 						ignore (traverse init_list right_expr)
 					| TWhile (condition, body, DoWhile) ->
@@ -1656,18 +1778,7 @@ class class_checker cls immediate_execution report =
 				);
 				init_list
 			in
-			(match cls.cl_constructor with
-				| Some { cf_expr = Some { eexpr = TFunction { tf_expr = e } } } ->
-					ignore (traverse fields_to_initialize e);
-				| _ -> ()
-			);
-			Hashtbl.iter
-				(fun name field ->
-					checker#error
-						("Field \"" ^ name ^ "\" is not nullable thus should have an initial value or should be initialized in constructor.")
-						[field.cf_pos]
-				)
-				fields_to_initialize
+			traverse fields_to_initialize tf_expr
 	end
 
 (**
@@ -1682,7 +1793,7 @@ let run (com:Common.context) (types:module_type list) =
 				| TEnumDecl enm -> ()
 				| TTypeDecl typedef -> ()
 				| TAbstractDecl abstr -> ()
-				| TClassDecl cls -> (new class_checker cls immediate_execution report)#check
+				| TClassDecl cls -> (new class_checker cls immediate_execution report com.main.main_expr)#check
 		in
 		List.iter traverse types;
 		report;

+ 8 - 5
src/typing/operators.ml

@@ -451,7 +451,7 @@ let find_abstract_binop_overload ctx op e1 e2 a c tl left is_assign_op p =
 	let is_eq_op = match op with OpEq | OpNotEq -> true | _ -> false in
 	if is_eq_op then begin match follow e1.etype,follow e2.etype with
 		| TMono _,_ | _,TMono _ ->
-			Type.unify e1.etype e2.etype
+			(try Type.unify e1.etype e2.etype with Unify_error _ -> () (* this will fail later again *));
 		| _ ->
 			()
 	end;
@@ -677,7 +677,8 @@ type 'a assign_op_api = {
 
 let handle_assign_op ctx api e1 e2 with_type p =
 	let field_rhs_by_name name ev with_type =
-		let access_get = type_field_default_cfg ctx ev name p MGet with_type in
+		let field_pos = snd e1 in
+		let access_get = type_field_default_cfg ctx ev name field_pos MGet with_type in
 		let e_get = acc_get ctx access_get in
 		e_get,api.type_rhs e_get e2
 	in
@@ -944,7 +945,8 @@ let type_unop ctx op flag e with_type p =
 				e_lhs,None
 		in
 		let read_on vr ef fa =
-			let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name p MGet WithType.value in
+			let field_pos = snd e in
+			let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name field_pos MGet WithType.value in
 			let e_lhs = acc_get ctx access_get in
 			let e_lhs,e_out = maybe_tempvar_postfix vr e_lhs in
 			e_lhs,e_out
@@ -969,7 +971,8 @@ let type_unop ctx op flag e with_type p =
 			| AKField fa ->
 				let vr = new value_reference ctx in
 				let ef = vr#get_expr_part "fh" fa.fa_on in
-				let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name p MGet WithType.value in
+				let field_pos = snd e in
+				let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name field_pos MGet WithType.value in
 				let e,e_out = match access_get with
 				| AKField _ ->
 					let e = FieldAccess.get_field_expr {fa with fa_on = ef} FGet in
@@ -1028,4 +1031,4 @@ let type_unop ctx op flag e with_type p =
 			| AKUsingField _ | AKResolve _ ->
 				raise_typing_error "Invalid operation" p
 		in
-		loop (!type_access_ref ctx (fst e) (snd e) (MSet None) WithType.value (* WITHTYPETODO *))
+		loop (!type_access_ref ctx (fst e) (snd e) (MSet None) WithType.value (* WITHTYPETODO *))

+ 3 - 0
src/typing/typeload.ml

@@ -582,6 +582,8 @@ and load_complex_type' ctx allow_display mode (t,p) =
 						| "dynamic" -> AccCall
 						| "get" when get -> AccCall
 						| "set" when not get -> AccCall
+						| "private get" when get -> AccPrivateCall
+						| "private set" when not get -> AccPrivateCall
 						| x when get && x = "get_" ^ n -> AccCall
 						| x when not get && x = "set_" ^ n -> AccCall
 						| _ ->
@@ -793,6 +795,7 @@ let load_core_class ctx c =
 			com2.defines.Define.values <- PMap.empty;
 			Common.define com2 Define.CoreApi;
 			Common.define com2 Define.Sys;
+			allow_package com2 "sys";
 			Define.raw_define_value com2.defines "target.threaded" "true"; (* hack because we check this in sys.thread classes *)
 			if ctx.com.is_macro_context then Common.define com2 Define.Macro;
 			com2.class_paths#lock_context (platform_name_macro ctx.com) true;

+ 12 - 5
src/typing/typeloadCheck.ml

@@ -65,10 +65,10 @@ let valid_redefinition map1 map2 f1 t1 f2 t2 = (* child, parent *)
 	begin match f1.cf_kind,f2.cf_kind with
 	| Method m1, Method m2 when not (m1 = MethDynamic) && not (m2 = MethDynamic) ->
 		begin match follow t1, follow t2 with
-		| TFun (args1,r1) , TFun (args2,r2) -> (
+		| TFun (args1,r1) , TFun (args2,r2) ->
 			if not (List.length args1 = List.length args2) then raise (Unify_error [Unify_custom "Different number of function arguments"]);
 			let i = ref 0 in
-			try
+			begin try
 				valid r1 r2;
 				List.iter2 (fun (n,o1,a1) (_,o2,a2) ->
 					incr i;
@@ -77,7 +77,8 @@ let valid_redefinition map1 map2 f1 t1 f2 t2 = (* child, parent *)
 				) args1 args2;
 			with Unify_error l ->
 				let msg = if !i = 0 then Invalid_return_type else Invalid_function_argument(!i,List.length args1) in
-				raise (Unify_error (Cannot_unify (t1,t2) :: msg :: l)))
+				raise (Unify_error (Cannot_unify (t1,t2) :: msg :: l))
+			end
 		| _ ->
 			die "" __LOC__
 		end
@@ -106,7 +107,13 @@ let valid_redefinition map1 map2 f1 t1 f2 t2 = (* child, parent *)
 		| ct1,ct2 ->
 			List.iter (fun t2 ->
 				let t2 = map2 t2 in
-				if not (List.exists (fun t1 -> does_unify (map1 t1) t2) ct1) then
+				if not (List.exists (fun t1 ->
+					try
+						Type.unify_custom uctx (map1 t1) t2;
+						true
+					with Unify_error _ ->
+						false
+				) ct1) then
 					raise (Unify_error ([Unify_custom (Printf.sprintf "Constraint unsatisfied for type parameter %s: %s" ttp2.ttp_name (s_type (print_context()) t2))]))
 			) ct2
 	in
@@ -384,7 +391,7 @@ module Inheritance = struct
 					if (has_class_field_flag f CfPublic) && not (has_class_field_flag f2 CfPublic) && not (Meta.has Meta.CompilerGenerated f.cf_meta) then
 						display_error com ("Field " ^ f.cf_name ^ " should be public as requested by " ^ s_type_path intf.cl_path) p
 					else if not (unify_kind ~strict:false f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then
-						display_error com ("Field " ^ f.cf_name ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p
+						display_error com ("Field " ^ f.cf_name ^ " has different property access than in " ^ s_type_path intf.cl_path ^ ": " ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind) p
 					else try
 						let map1 = TClass.get_map_function  intf params in
 						valid_redefinition map1 map2 f2 t2 f (apply_params intf.cl_params params f.cf_type)

+ 24 - 9
src/typing/typeloadFields.ml

@@ -734,7 +734,7 @@ module TypeBinding = struct
 		let c = cctx.tclass in
 		let t = cf.cf_type in
 		let p = cf.cf_pos in
-		let ctx = TyperManager.clone_for_expr ctx_f (if fctx.is_static then FunStatic else FunMember) false in
+		let ctx = TyperManager.clone_for_expr ctx_f (if fctx.is_static then FunStatic else FunMember) FunNotFunction in
 		if (has_class_flag c CInterface) then unexpected_expression ctx.com fctx "Initialization on field of interface" (pos e);
 		cf.cf_meta <- ((Meta.Value,[e],mk_zero_range_pos cf.cf_pos) :: cf.cf_meta);
 		let check_cast e =
@@ -825,9 +825,9 @@ module TypeBinding = struct
 		| Some e ->
 			bind_var_expression ctx cctx fctx cf e
 
-	let bind_method ctx_f cctx fctx fmode cf t args ret e p =
+	let bind_method ctx_f cctx fctx fmode cf t args ret e function_mode p =
 		let c = cctx.tclass in
-		let ctx = TyperManager.clone_for_expr ctx_f fmode true in
+		let ctx = TyperManager.clone_for_expr ctx_f fmode function_mode in
 		let bind () =
 			incr stats.s_methods_typed;
 			if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.com.is_macro_context then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name);
@@ -1142,7 +1142,8 @@ let setup_args_ret ctx cctx fctx name fd p =
 		let name = String.sub name 4 (String.length name - 4) in
 		let cf = if fctx.is_static then PMap.find name c.cl_statics else PMap.find name c.cl_fields (* TODO: inheritance? *) in
 		match Lazy.force mk, cf.cf_kind with
-			| MKGetter, Var({v_read = AccCall}) | MKSetter, Var({v_write = AccCall}) -> cf.cf_type
+			| MKGetter, Var({v_read = AccCall | AccPrivateCall})
+			| MKSetter, Var({v_write = AccCall | AccPrivateCall}) -> cf.cf_type
 			| _ -> raise Not_found;
 	in
 	let maybe_use_property_type th check def =
@@ -1256,7 +1257,9 @@ let create_method (ctx,cctx,fctx) c f cf fd p =
 
 	ctx.type_params <- params @ ctx.type_params;
 	let args,ret = setup_args_ret ctx cctx fctx (fst f.cff_name) fd p in
-	let t = TFun (args#for_type,ret) in
+	let function_mode = FunFunction in
+	let targs = args#for_type in
+	let t = TFun (targs,ret) in
 	cf.cf_type <- t;
 	cf.cf_kind <- Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal);
 	cf.cf_params <- params;
@@ -1327,18 +1330,18 @@ let create_method (ctx,cctx,fctx) c f cf fd p =
 	in
 	init_meta_overloads ctx (Some c) cf;
 	if fctx.do_bind then
-		TypeBinding.bind_method ctx cctx fctx fmode cf t args ret fd.f_expr (match fd.f_expr with Some e -> snd e | None -> f.cff_pos)
+		TypeBinding.bind_method ctx cctx fctx fmode cf t args ret fd.f_expr function_mode (match fd.f_expr with Some e -> snd e | None -> f.cff_pos)
 	else begin
 		if fctx.is_display_field then begin
 			delay ctx.g PTypeField (fun () ->
 				(* We never enter type_function so we're missing out on the argument processing there. Let's do it here. *)
-				let ctx = TyperManager.clone_for_expr ctx fmode true in
+				let ctx = TyperManager.clone_for_expr ctx fmode function_mode in
 				ignore(args#for_expr ctx)
 			);
 			check_field_display ctx fctx c cf;
 		end else
 			delay ctx.g PTypeField (fun () ->
-				let ctx = TyperManager.clone_for_expr ctx fmode true in
+				let ctx = TyperManager.clone_for_expr ctx fmode function_mode in
 				args#verify_extern ctx
 			);
 		if fd.f_expr <> None then begin
@@ -1457,6 +1460,11 @@ let create_property (ctx,cctx,fctx) c f cf (get,set,t,eo) p =
 			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pget then delay ctx.g PConnectField (fun () -> display_accessor get pget);
 			if not cctx.is_lib then delay_check (fun() -> check_method get t_get true);
 			AccCall
+		| "private get",pget ->
+			let get = "get_" ^ name in
+			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pget then delay ctx.g PConnectField (fun () -> display_accessor get pget);
+			if not cctx.is_lib then delay_check (fun() -> check_method get t_get true);
+			AccPrivateCall
 		| _,pget ->
 			display_error ctx.com (name ^ ": Custom property accessor is no longer supported, please use `get`") pget;
 			AccCall
@@ -1476,11 +1484,18 @@ let create_property (ctx,cctx,fctx) c f cf (get,set,t,eo) p =
 			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pset then delay ctx.g PConnectField (fun () -> display_accessor set pset);
 			if not cctx.is_lib then delay_check (fun() -> check_method set t_set false);
 			AccCall
+		| "private set",pset ->
+			let set = "set_" ^ name in
+			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pset then delay ctx.g PConnectField (fun () -> display_accessor set pset);
+			if not cctx.is_lib then delay_check (fun() -> check_method set t_set false);
+			AccPrivateCall
 		| _,pset ->
 			display_error ctx.com (name ^ ": Custom property accessor is no longer supported, please use `set`") pset;
 			AccCall
 	) in
-	if (set = AccNever && get = AccNever)  then raise_typing_error (name ^ ": Unsupported property combination") p;
+	if (set = AccNever && get = AccNever) then raise_typing_error (name ^ ": Unsupported property combination") p;
+	if (set = AccPrivateCall && get = AccPrivateCall && has_class_field_flag cf CfPublic) then
+		raise_typing_error (name ^ ": (private get, private set) property cannot be public") p;
 	cf.cf_kind <- Var { v_read = get; v_write = set };
 	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	if List.mem_assoc AEnum f.cff_access then add_class_field_flag cf CfEnum;

+ 0 - 1
src/typing/typeloadModule.ml

@@ -27,7 +27,6 @@ open DisplayTypes.DisplayMode
 open Common
 open Typeload
 open Error
-open Resolution
 
 let get_policy g mpath =
 	let sl1 = full_dot_path2 mpath mpath in

+ 18 - 11
src/typing/typer.ml

@@ -693,29 +693,35 @@ and type_object_decl ctx fl with_type p =
 		let fl = List.map (fun ((n,pn,qs),e) ->
 			let is_valid = Lexer.is_valid_identifier n in
 			if PMap.mem n !fields then raise_typing_error ("Duplicate field in object declaration : " ^ n) pn;
-			let is_final = ref false in
-			let e = try
-				let t = match !dynamic_parameter with
-					| Some t -> t
+			let e,cfo = try
+				let t,cfo = match !dynamic_parameter with
+					| Some t ->
+						t,None
 					| None ->
 						let cf = PMap.find n field_map in
-						if (has_class_field_flag cf CfFinal) then is_final := true;
 						if ctx.f.in_display && DisplayPosition.display_position#enclosed_in pn then DisplayEmitter.display_field ctx Unknown CFSMember cf pn;
-						cf.cf_type
+						cf.cf_type,Some cf
 				in
 				let e = type_expr ctx e (WithType.with_structure_field t n) in
 				let e = AbstractCast.cast_or_unify ctx t e e.epos in
 				let e = if is_null t && not (is_null e.etype) then mk (TCast(e,None)) (ctx.t.tnull e.etype) e.epos else e in
-				(try type_eq EqStrict e.etype t; e with Unify_error _ -> mk (TCast (e,None)) t e.epos)
+				(try type_eq EqStrict e.etype t; e with Unify_error _ -> mk (TCast (e,None)) t e.epos),cfo
 			with Not_found ->
 				if is_valid then
 					extra_fields := (n,pn) :: !extra_fields;
-				type_expr ctx e WithType.value
+				type_expr ctx e WithType.value,None
 			in
 			if is_valid then begin
 				if starts_with n '$' then raise_typing_error "Field names starting with a dollar are not allowed" p;
 				let cf = mk_field n e.etype (punion pn e.epos) pn in
-				if !is_final then add_class_field_flag cf CfFinal;
+				begin match cfo with
+					| Some cf' ->
+						(* If we're assigning to an existing field, copy some of its characteristics *)
+						if has_class_field_flag cf' CfFinal then add_class_field_flag cf CfFinal;
+						cf.cf_kind <- cf'.cf_kind;
+					| None ->
+						()
+				end;
 				fields := PMap.add n cf !fields;
 			end;
 			((n,pn,qs),e)
@@ -1109,7 +1115,8 @@ and type_local_function ctx_from kind f with_type p =
 		| FunMemberAbstractLocal -> FunMemberAbstractLocal
 		| _ -> FunMemberClassLocal
 	in
-	let ctx = TyperManager.clone_for_expr ctx_from curfun true in
+	let function_mode = FunFunction in
+	let ctx = TyperManager.clone_for_expr ctx_from curfun function_mode in
 	let vname,pname= match name with
 		| None ->
 			if params <> [] then begin
@@ -1850,7 +1857,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 		let e = Matcher.Match.match_expr ctx e1 cases def with_type false p in
 		wrap e
 	| EReturn e ->
-		if not ctx.e.in_function then begin
+		if not (TyperManager.is_function_context ctx) then begin
 			display_error ctx.com "Return outside function" p;
 			match e with
 			| None ->

+ 51 - 1
src/typing/typerEntry.ml

@@ -135,6 +135,55 @@ let load_enum_tools ctx =
 	| _ ->
 		die "" __LOC__
 
+let load_local_wrapper ctx =
+	let t = ctx.t in
+	match ctx.com.platform with
+	(* optimized version for Java - use native arrays *)
+	| Jvm ->
+		let cnativearray =
+			let m = TypeloadModule.load_module ctx (["jvm"],"NativeArray") null_pos in
+			let mt = List.find (fun md -> match md with
+					| TClassDecl ({ cl_path = ["jvm"],"NativeArray" }) -> true
+					| _ -> false
+				) m.m_types
+			in
+			match mt with
+			| TClassDecl cl -> cl
+			| _ -> die "" __LOC__
+		in
+
+		object
+			method captured_type t = TInst (cnativearray,[t])
+
+			method mk_ref v ve p =
+				match ve with
+				| None ->
+					let eone = mk (TConst (TInt (Int32.of_int 1))) t.tint p in
+					let t = match v.v_type with TInst (_, [t]) -> t | _ -> die "" __LOC__ in
+					mk (TNew (cnativearray,[t],[eone])) v.v_type p
+				| Some e ->
+					{ (Inline.mk_untyped_call "__array__" p [e]) with etype = v.v_type }
+
+			method mk_ref_access e v =
+				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
+
+			method mk_init av v pos =
+				let elocal = mk (TLocal v) v.v_type pos in
+				let earray = { (Inline.mk_untyped_call "__array__" pos [elocal]) with etype = av.v_type } in
+				mk (TVar (av,Some earray)) t.tvoid pos
+		end
+	(* default implementation - use haxe array *)
+	| _ ->
+		object
+			method captured_type = t.tarray
+			method mk_ref v ve p =
+				mk (TArrayDecl (match ve with None -> [] | Some e -> [e])) v.v_type p
+			method mk_ref_access e v =
+				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
+			method mk_init av v pos =
+				mk (TVar (av,Some (mk (TArrayDecl [mk (TLocal v) v.v_type pos]) av.v_type pos))) t.tvoid pos
+		end
+
 let create com macros =
 	let rec ctx = {
 		com = com;
@@ -179,7 +228,7 @@ let create com macros =
 			get_build_infos = (fun() -> None);
 		};
 		f = TyperManager.create_ctx_f null_field;
-		e = TyperManager.create_ctx_e FunStatic false;
+		e = TyperManager.create_ctx_e FunStatic FunFunction;
 		pass = PBuildModule;
 		allow_inline = true;
 		allow_transform = true;
@@ -194,6 +243,7 @@ let create com macros =
 	load_array ctx;
 	load_enum_tools ctx;
 	ignore(TypeloadModule.load_module ctx (["haxe"],"Exception") null_pos);
+	ctx.com.local_wrapper <- load_local_wrapper ctx;
 	ctx.g.complete <- true;
 	ctx
 

+ 8 - 1
std/cpp/_std/haxe/Exception.hx

@@ -4,7 +4,7 @@ package haxe;
 @:coreApi
 class Exception {
 	public var message(get,never):String;
-	public var stack(get,never):CallStack;
+	public var stack(get,set):CallStack;
 	public var previous(get,never):Null<Exception>;
 	public var native(get,never):Any;
 
@@ -14,6 +14,7 @@ class Exception {
 	@:noCompletion @:ifFeature("haxe.Exception.get_stack") var __skipStack:Int = 0;
 	@:noCompletion var __nativeException:Any;
 	@:noCompletion var __previousException:Null<Exception>;
+	@:noCompletion var _hx_customStack:Null<String>;
 
 	static function caught(value:Any):Exception {
 		if(Std.isOfType(value, Exception)) {
@@ -90,5 +91,11 @@ class Exception {
 			case s: s;
 		}
 	}
+
+	function set_stack(stack:CallStack) {
+		_hx_customStack = CallStack.toString(stack);
+
+		return __exceptionStack = stack;
+	}
 }
 

+ 47 - 0
std/cpp/_std/haxe/atomic/AtomicBool.hx

@@ -0,0 +1,47 @@
+package haxe.atomic;
+
+#if doc_gen
+@:coreApi
+@:coreType
+abstract AtomicBool {
+	public function new(value:Bool):Void;
+
+	public function compareExchange(expected:Bool, replacement:Bool):Bool;
+
+	public function exchange(value:Bool):Bool;
+
+	public function load():Bool;
+
+	public function store(value:Bool):Bool;
+}
+#else
+abstract AtomicBool(AtomicInt) {
+	private inline function toInt(v:Bool):Int {
+		return v ? 1 : 0;
+	}
+
+	private inline function toBool(v:Int):Bool {
+		return v == 1;
+	}
+
+	public inline function new(value:Bool):Void {
+		this = new AtomicInt(toInt(value));
+	}
+
+	public inline function compareExchange(expected:Bool, replacement:Bool):Bool {
+		return toBool(this.compareExchange(toInt(expected), toInt(replacement)));
+	}
+
+	public inline function exchange(value:Bool):Bool {
+		return toBool(this.exchange(toInt(value)));
+	}
+
+	public inline function load():Bool {
+		return toBool(this.load());
+	}
+
+	public inline function store(value:Bool):Bool {
+		return toBool(this.store(toInt(value)));
+	}
+}
+#end

+ 43 - 11
std/cpp/_std/haxe/atomic/AtomicInt.hx

@@ -1,9 +1,40 @@
 package haxe.atomic;
 
+#if doc_gen
+@:coreApi
+@:coreType
+abstract AtomicInt {
+	public function new(value:Int):Void;
+
+	public function add(b:Int):Int;
+
+	public function sub(b:Int):Int;
+
+	public function and(b:Int):Int;
+
+	public function or(b:Int):Int;
+
+	public function xor(b:Int):Int;
+
+	public function compareExchange(expected:Int, replacement:Int):Int;
+
+	public function exchange(value:Int):Int;
+
+	public function load():Int;
+
+	public function store(value:Int):Int;
+}
+#else
+private final class Data {
+	public var value:Int;
+	public function new(value:Int) {
+		this.value = value;
+	}
+}
 #if cppia
 extern
 #end
-abstract AtomicInt(cpp.Pointer<Int>) {
+abstract AtomicInt(Data) {
 	#if cppia
 	public function new(value:Int):Void;
 
@@ -26,43 +57,44 @@ abstract AtomicInt(cpp.Pointer<Int>) {
 	public function store(value:Int):Int;
 	#else
 	public #if !scriptable inline #end function new(value:Int) {
-		this = cpp.Pointer.ofArray([value]);
+		this = new Data(value);
 	}
 
 	public #if !scriptable inline #end function add(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_add({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_add(&{0}, {1})", this.value, b);
 	}
 
 	public #if !scriptable inline #end function sub(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_sub({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_sub(&{0}, {1})", this.value, b);
 	}
 
 	public #if !scriptable inline #end function and(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_and({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_and(&{0}, {1})", this.value, b);
 	}
 
 	public #if !scriptable inline #end function or(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_or({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_or(&{0}, {1})", this.value, b);
 	}
 
 	public #if !scriptable inline #end function xor(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_xor({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_xor(&{0}, {1})", this.value, b);
 	}
 
 	public #if !scriptable inline #end function compareExchange(expected:Int, replacement:Int):Int {
-		return untyped __cpp__("_hx_atomic_compare_exchange({0}, {1}, {2})", this, expected, replacement);
+		return untyped __cpp__("_hx_atomic_compare_exchange(&{0}, {1}, {2})", this.value, expected, replacement);
 	}
 
 	public #if !scriptable inline #end function exchange(value:Int):Int {
-		return untyped __cpp__("_hx_atomic_exchange({0}, {1})", this, value);
+		return untyped __cpp__("_hx_atomic_exchange(&{0}, {1})", this.value, value);
 	}
 
 	public #if !scriptable inline #end function load():Int {
-		return untyped __cpp__("_hx_atomic_load({0})", this);
+		return untyped __cpp__("_hx_atomic_load(&{0})", this.value);
 	}
 
 	public #if !scriptable inline #end function store(value:Int):Int {
-		return untyped __cpp__("_hx_atomic_store({0}, {1})", this, value);
+		return untyped __cpp__("_hx_atomic_store(&{0}, {1})", this.value, value);
 	}
 	#end
 }
+#end

+ 2 - 0
std/eval/_std/Sys.hx

@@ -75,6 +75,8 @@ class Sys {
 
 	extern static public function time():Float;
 
+	extern static function timestamp_ms():haxe.Int64;
+
 	extern static public function cpuTime():Float;
 
 	extern static public function programPath():String;

+ 16 - 1
std/eval/_std/haxe/Exception.hx

@@ -3,7 +3,7 @@ package haxe;
 @:coreApi
 class Exception {
 	public var message(get,never):String;
-	public var stack(get,never):CallStack;
+	public var stack(get,set):CallStack;
 	public var previous(get,never):Null<Exception>;
 	public var native(get,never):Any;
 
@@ -13,6 +13,7 @@ class Exception {
 	@:noCompletion @:ifFeature("haxe.Exception.get_stack") var __skipStack:Int = 0;
 	@:noCompletion var __nativeException:Any;
 	@:noCompletion var __previousException:Null<Exception>;
+	@:noCompletion var __customStack:haxe.ds.Vector<Dynamic>;
 
 	static function caught(value:Any):Exception {
 		if(Std.isOfType(value, Exception)) {
@@ -95,4 +96,18 @@ class Exception {
 			case s: s;
 		}
 	}
+
+	function set_stack(stack:CallStack) {
+		var items = stack.asArray();
+		var a:Array<Dynamic> = [];
+		for (item in items) {
+			switch (item) {
+				case FilePos(Method(_), _):
+					a.push(item);
+				case _:
+			}
+		}
+		__customStack = haxe.ds.Vector.fromArrayCopy(a);
+		return __nativeStack = __exceptionStack = stack;
+	}
 }

+ 5 - 1
std/flash/_std/haxe/Exception.hx

@@ -5,7 +5,7 @@ import flash.errors.Error;
 @:coreApi
 class Exception extends NativeException {
 	public var message(get,never):String;
-	public var stack(get,never):CallStack;
+	public var stack(get,set):CallStack;
 	public var previous(get,never):Null<Exception>;
 	public var native(get,never):Any;
 
@@ -86,6 +86,10 @@ class Exception extends NativeException {
 			case s: s;
 		}
 	}
+
+	function set_stack(stack:CallStack) {
+		return __exceptionStack = stack;
+	}
 }
 
 @:dox(hide)

+ 1 - 1
std/haxe/CallStack.hx

@@ -112,7 +112,7 @@ abstract CallStack(Array<StackItem>) from Array<StackItem> {
 		return this[index];
 	}
 
-	inline function asArray():Array<StackItem> {
+	public inline function asArray():Array<StackItem> {
 		return this;
 	}
 

+ 2 - 1
std/haxe/Exception.hx

@@ -51,8 +51,9 @@ extern class Exception {
 	/**
 		The call stack at the moment of the exception creation.
 	**/
-	public var stack(get,never):CallStack;
+	public var stack(get,set):CallStack;
 	private function get_stack():CallStack;
+	private function set_stack(stack:CallStack):CallStack;
 
 	/**
 		Contains an exception, which was passed to `previous` constructor argument.

+ 36 - 1
std/haxe/Timer.hx

@@ -22,6 +22,7 @@
 
 package haxe;
 
+import haxe.Int64;
 #if (target.threaded && !cppia)
 import sys.thread.Thread;
 import sys.thread.EventLoop;
@@ -43,7 +44,7 @@ import sys.thread.EventLoop;
 
 	Notice for threaded targets:
 	`Timer` instances require threads they were created in to run with Haxe's event loops.
-	Main thread of a Haxe program always contains an event loop. For other cases use 
+	Main thread of a Haxe program always contains an event loop. For other cases use
 	`sys.thread.Thread.createWithEventLoop` and `sys.thread.Thread.runWithEventLoop` methods.
 **/
 class Timer {
@@ -195,4 +196,38 @@ class Timer {
 		return 0;
 		#end
 	}
+
+	/**
+	 * Returns a monotonically increasing timestamp with millisecond resolution.
+	 *
+	 * The precision and epoch of the timer is platform defined.
+	 */
+	public static inline function milliseconds():Int64 {
+		#if flash
+		return flash.Lib.getTimer();
+		#elseif js
+		#if nodejs
+		var hrtime = js.Syntax.code('process.hrtime()'); // [seconds, remaining nanoseconds]
+		return hrtime[0] * 1000 + (hrtime[1] / 1000000i64);
+		#else
+		return Std.int(@:privateAccess HxOverrides.now());
+		#end
+		#elseif cpp
+		return untyped __global__.__time_stamp_ms();
+		#elseif python
+		#if (python_version >= 3.7)
+		return python.lib.Time.perf_counter_ns() / 1000000i64;
+		#else
+		return Std.int(stamp() * 1000);
+		#end
+		#elseif (hl && hl_ver >= version("1.16.0"))
+		return hl.Api.timestampMs();
+		#elseif jvm
+		return java.lang.System.nanoTime() / 1000000i64;
+		#elseif eval
+		return @:privateAccess Sys.timestamp_ms();
+		#else
+		return Int64.mul(Int64.fromFloat(stamp()), 1000);
+		#end
+	}
 }

+ 8 - 27
std/haxe/atomic/AtomicBool.hx

@@ -9,47 +9,28 @@ package haxe.atomic;
 	(js) The Atomics and SharedArrayBuffer objects need to be available. Errors will be thrown if this is not the case.
 **/
 @:coreApi
-abstract AtomicBool(AtomicInt) {
-	private inline function toInt(v:Bool):Int {
-		return v ? 1 : 0;
-	}
-
-	private inline function toBool(v:Int):Bool {
-		return v == 1;
-	}
-
-	public inline function new(value:Bool):Void {
-		this = new AtomicInt(toInt(value));
-	}
+@:coreType
+abstract AtomicBool {
+	public function new(value:Bool):Void;
 
 	/**
 		Atomically compares the value of `a` with `expected` and replaces `a` with `replacement` if they are equal..
 		Returns the original value of `a`.
 	**/
-	public inline function compareExchange(expected:Bool, replacement:Bool):Bool {
-		return toBool(this.compareExchange(toInt(expected), toInt(replacement)));
-	}
+	public function compareExchange(expected:Bool, replacement:Bool):Bool;
 
 	/**
 		Atomically exchanges `a` with `value`.
 		Returns the original value of `a`.
 	**/
-	public inline function exchange(value:Bool):Bool {
-		return toBool(this.exchange(toInt(value)));
-	}
-
+	public function exchange(value:Bool):Bool;
 	/**
 		Atomically fetches the value of `a`.
 	**/
-	public inline function load():Bool {
-		return toBool(this.load());
-	}
-
+	public function load():Bool;
 	/**
 		Atomically stores `value` into `a`.
 		Returns the value that has been stored.
 	**/
-	public inline function store(value:Bool):Bool {
-		return toBool(this.store(toInt(value)));
-	}
-}
+	public function store(value:Bool):Bool;
+}

+ 1 - 0
std/haxe/display/JsonModuleTypes.hx

@@ -213,6 +213,7 @@ enum abstract JsonVarAccessKind<T>(String) {
 	var AccNever;
 	var AccResolve;
 	var AccCall;
+	var AccPrivateCall;
 	var AccInline;
 	var AccRequire:JsonVarAccessKind<{require:String, message:Null<String>}>;
 	var AccCtor;

Vissa filer visades inte eftersom för många filer har ändrats