--- old/src/share/vm/ci/ciMethodBlocks.cpp Mon Aug 2 14:26:18 2010 +++ new/src/share/vm/ci/ciMethodBlocks.cpp Mon Aug 2 14:26:18 2010 @@ -252,7 +252,7 @@ _arena(arena), _num_blocks(0), _code_size(meth->code_size()) { int block_estimate = _code_size / 8; - _blocks = new(_arena) GrowableArray(block_estimate); + _blocks = new(_arena) GrowableArray(_arena, block_estimate, 0, NULL); int b2bsize = _code_size * sizeof(ciBlock **); _bci_to_block = (ciBlock **) arena->Amalloc(b2bsize); Copy::zero_to_words((HeapWord*) _bci_to_block, b2bsize / sizeof(HeapWord)); --- old/src/share/vm/ci/ciTypeFlow.cpp Mon Aug 2 14:26:18 2010 +++ new/src/share/vm/ci/ciTypeFlow.cpp Mon Aug 2 14:26:18 2010 @@ -2591,7 +2591,7 @@ StateVector* temp_vector, JsrSet* temp_set) { int dft_len = 100; - GrowableArray stk(arena(), dft_len, 0, NULL); + GrowableArray stk(dft_len); ciBlock* dummy = _methodBlocks->make_dummy_block(); JsrSet* root_set = new JsrSet(NULL, 0); --- old/src/share/vm/memory/allocation.cpp Mon Aug 2 14:26:19 2010 +++ new/src/share/vm/memory/allocation.cpp Mon Aug 2 14:26:19 2010 @@ -43,15 +43,15 @@ switch (type) { case C_HEAP: res = (address)AllocateHeap(size, "C_Heap: ResourceOBJ"); + DEBUG_ONLY(set_allocation_type(res, C_HEAP);) break; case RESOURCE_AREA: + // Will set allocation type in the resource object. res = (address)operator new(size); break; default: ShouldNotReachHere(); } - // Set allocation type in the resource object for assertion checks. - DEBUG_ONLY(((ResourceObj *)res)->_allocation = type;) return res; } --- old/src/share/vm/memory/allocation.hpp Mon Aug 2 14:26:19 2010 +++ new/src/share/vm/memory/allocation.hpp Mon Aug 2 14:26:19 2010 @@ -316,12 +316,34 @@ // use delete to deallocate. class ResourceObj ALLOCATION_SUPER_CLASS_SPEC { public: - enum allocation_type { UNKNOWN = 0, C_HEAP, RESOURCE_AREA, ARENA }; + enum allocation_type { RESOURCE_AREA = 0, C_HEAP, ARENA, allocation_mask = 0x3 }; #ifdef ASSERT private: - allocation_type _allocation; + // When this object is allocated on stack the new() operator is not + // called but garbage on stack may look like a valid allocation_type. + // Store negated 'this' pointer when new() is called to distinguish cases. + uintptr_t _allocation; + static void set_allocation_type(address res, allocation_type type) { + // Set allocation type in the resource object + uintptr_t allocation = (uintptr_t)res; + assert((allocation & allocation_mask) == 0, ""); + assert(type < allocation_mask, ""); + ((ResourceObj *)res)->_allocation = ~(allocation + type); + } + allocation_type get_allocation_type() { + return (allocation_type)((~_allocation) & allocation_mask); + } public: - bool allocated_on_C_heap() { return _allocation == C_HEAP; } + bool allocated_on_stack() { return get_allocation_type() == RESOURCE_AREA; } + bool allocated_on_C_heap() { return get_allocation_type() == C_HEAP; } + bool allocated_on_arena() { return get_allocation_type() == ARENA; } + ResourceObj() { + if (~(_allocation | allocation_mask) != (uintptr_t)this) { + set_allocation_type((address)this, RESOURCE_AREA); + } else { + assert(allocated_on_stack() || allocated_on_C_heap() || allocated_on_arena(), ""); + } + } #endif // ASSERT public: @@ -328,20 +350,17 @@ void* operator new(size_t size, allocation_type type); void* operator new(size_t size, Arena *arena) { address res = (address)arena->Amalloc(size); - // Set allocation type in the resource object - DEBUG_ONLY(((ResourceObj *)res)->_allocation = ARENA;) + DEBUG_ONLY(set_allocation_type(res, ARENA);) return res; } void* operator new(size_t size) { address res = (address)resource_allocate_bytes(size); - // Set allocation type in the resource object - DEBUG_ONLY(((ResourceObj *)res)->_allocation = RESOURCE_AREA;) + DEBUG_ONLY(set_allocation_type(res, RESOURCE_AREA);) return res; } void* operator new(size_t size, void* where, allocation_type type) { - void* res = where; - // Set allocation type in the resource object - DEBUG_ONLY(((ResourceObj *)res)->_allocation = type;) + address res = (address)where; + DEBUG_ONLY(set_allocation_type(res, C_HEAP);) return res; } void operator delete(void* p); --- old/src/share/vm/opto/c2_globals.hpp Mon Aug 2 14:26:20 2010 +++ new/src/share/vm/opto/c2_globals.hpp Mon Aug 2 14:26:20 2010 @@ -281,6 +281,9 @@ product(bool, InsertMemBarAfterArraycopy, true, \ "Insert memory barrier after arraycopy call") \ \ + develop(bool, SubsumeLoads, true, \ + "Attempt to compile while subsuming loads into machine instructions.") \ + \ /* controls for tier 1 compilations */ \ \ develop(bool, Tier1CountInvocations, true, \ --- old/src/share/vm/opto/c2compiler.cpp Mon Aug 2 14:26:20 2010 +++ new/src/share/vm/opto/c2compiler.cpp Mon Aug 2 14:26:20 2010 @@ -103,7 +103,7 @@ if (!is_initialized()) { initialize(); } - bool subsume_loads = true; + bool subsume_loads = SubsumeLoads; bool do_escape_analysis = DoEscapeAnalysis && !env->jvmti_can_access_local_variables(); while (!env->failing()) { @@ -110,6 +110,7 @@ // Attempt to compile while subsuming loads into machine instructions. Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis); + // Check result and retry if appropriate. if (C.failure_reason() != NULL) { if (C.failure_reason_is(retry_no_subsuming_loads())) { @@ -127,6 +128,16 @@ // on the ciEnv via env->record_method_not_compilable(). env->record_failure(C.failure_reason()); } + if (CompileTheWorld) { + if (subsume_loads) { + subsume_loads = false; + continue; // retry + } + if (do_escape_analysis) { + do_escape_analysis = false; + continue; // retry + } + } // No retry; just break the loop. break; --- old/src/share/vm/opto/compile.cpp Mon Aug 2 14:26:21 2010 +++ new/src/share/vm/opto/compile.cpp Mon Aug 2 14:26:21 2010 @@ -904,8 +904,8 @@ probe_alias_cache(NULL)->_index = AliasIdxTop; _intrinsics = NULL; - _macro_nodes = new GrowableArray(comp_arena(), 8, 0, NULL); - _predicate_opaqs = new GrowableArray(comp_arena(), 8, 0, NULL); + _macro_nodes = new(comp_arena()) GrowableArray(comp_arena(), 8, 0, NULL); + _predicate_opaqs = new(comp_arena()) GrowableArray(comp_arena(), 8, 0, NULL); register_library_intrinsics(); } --- old/src/share/vm/utilities/growableArray.hpp Mon Aug 2 14:26:21 2010 +++ new/src/share/vm/utilities/growableArray.hpp Mon Aug 2 14:26:21 2010 @@ -97,7 +97,8 @@ assert(_len >= 0 && _len <= _max, "initial_len too big"); _arena = (c_heap ? (Arena*)1 : NULL); set_nesting(); - assert(!c_heap || allocated_on_C_heap(), "growable array must be on C heap if elements are"); + assert(!on_C_heap() || allocated_on_C_heap(), "growable array must be on C heap if elements are"); + assert(!on_stack () || allocated_on_stack(), "growable array must be on stack if elements are not on arena and not on C heap"); } // This GA will use the given arena for storage. @@ -108,6 +109,8 @@ assert(_len >= 0 && _len <= _max, "initial_len too big"); _arena = arena; assert(on_arena(), "arena has taken on reserved value 0 or 1"); + // Relax next assert to allow object allocation on resource area, stack or part of other object. + assert(allocated_on_arena() || allocated_on_stack(), "growable array must be on arena or on stack if elements are on arena"); } void* raw_allocate(int elementSize);