comparison src/share/vm/runtime/vframe.cpp @ 20501:c204e2044c29

8038624: interpretedVFrame::expressions() must respect InterpreterOopMap for liveness Reviewed-by: coleenp, minqi
author mgronlun
date Mon, 29 Sep 2014 13:12:48 +0200
parents 4a1062dc52d1
children 7848fc12602b
comparison
equal deleted inserted replaced
20500:46ffdf376cb5 20501:c204e2044c29
258 258
259 Method* interpretedVFrame::method() const { 259 Method* interpretedVFrame::method() const {
260 return fr().interpreter_frame_method(); 260 return fr().interpreter_frame_method();
261 } 261 }
262 262
263 static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask,
264 int index,
265 const intptr_t* const addr) {
266
267 assert(index >= 0 &&
268 index < oop_mask.number_of_entries(), "invariant");
269
270 // categorize using oop_mask
271 if (oop_mask.is_oop(index)) {
272 // reference (oop) "r"
273 Handle h(addr != NULL ? (*(oop*)addr) : (oop)NULL);
274 return new StackValue(h);
275 }
276 // value (integer) "v"
277 return new StackValue(addr != NULL ? *addr : 0);
278 }
279
280 static bool is_in_expression_stack(const frame& fr, const intptr_t* const addr) {
281 assert(addr != NULL, "invariant");
282
283 // Ensure to be 'inside' the expresion stack (i.e., addr >= sp for Intel).
284 // In case of exceptions, the expression stack is invalid and the sp
285 // will be reset to express this condition.
286 if (frame::interpreter_frame_expression_stack_direction() > 0) {
287 return addr <= fr.interpreter_frame_tos_address();
288 }
289
290 return addr >= fr.interpreter_frame_tos_address();
291 }
292
293 static void stack_locals(StackValueCollection* result,
294 int length,
295 const InterpreterOopMap& oop_mask,
296 const frame& fr) {
297
298 assert(result != NULL, "invariant");
299
300 for (int i = 0; i < length; ++i) {
301 const intptr_t* const addr = fr.interpreter_frame_local_at(i);
302 assert(addr != NULL, "invariant");
303 assert(addr >= fr.sp(), "must be inside the frame");
304
305 StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr);
306 assert(sv != NULL, "sanity check");
307
308 result->add(sv);
309 }
310 }
311
312 static void stack_expressions(StackValueCollection* result,
313 int length,
314 int max_locals,
315 const InterpreterOopMap& oop_mask,
316 const frame& fr) {
317
318 assert(result != NULL, "invariant");
319
320 for (int i = 0; i < length; ++i) {
321 const intptr_t* addr = fr.interpreter_frame_expression_stack_at(i);
322 assert(addr != NULL, "invariant");
323 if (!is_in_expression_stack(fr, addr)) {
324 // Need to ensure no bogus escapes.
325 addr = NULL;
326 }
327
328 StackValue* const sv = create_stack_value_from_oop_map(oop_mask,
329 i + max_locals,
330 addr);
331 assert(sv != NULL, "sanity check");
332
333 result->add(sv);
334 }
335 }
336
263 StackValueCollection* interpretedVFrame::locals() const { 337 StackValueCollection* interpretedVFrame::locals() const {
264 int length = method()->max_locals(); 338 return stack_data(false);
265 339 }
266 if (method()->is_native()) { 340
267 // If the method is native, max_locals is not telling the truth. 341 StackValueCollection* interpretedVFrame::expressions() const {
268 // maxlocals then equals the size of parameters 342 return stack_data(true);
269 length = method()->size_of_parameters(); 343 }
270 } 344
271 345 /*
272 StackValueCollection* result = new StackValueCollection(length); 346 * Worker routine for fetching references and/or values
273 347 * for a particular bci in the interpretedVFrame.
274 // Get oopmap describing oops and int for current bci 348 *
349 * Returns data for either "locals" or "expressions",
350 * using bci relative oop_map (oop_mask) information.
351 *
352 * @param expressions bool switch controlling what data to return
353 (false == locals / true == expressions)
354 *
355 */
356 StackValueCollection* interpretedVFrame::stack_data(bool expressions) const {
357
275 InterpreterOopMap oop_mask; 358 InterpreterOopMap oop_mask;
359 // oopmap for current bci
276 if (TraceDeoptimization && Verbose) { 360 if (TraceDeoptimization && Verbose) {
277 methodHandle m_h(thread(), method()); 361 methodHandle m_h(Thread::current(), method());
278 OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); 362 OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
279 } else { 363 } else {
280 method()->mask_for(bci(), &oop_mask); 364 method()->mask_for(bci(), &oop_mask);
281 } 365 }
366
367 const int mask_len = oop_mask.number_of_entries();
368
369 // If the method is native, method()->max_locals() is not telling the truth.
370 // For our purposes, max locals instead equals the size of parameters.
371 const int max_locals = method()->is_native() ?
372 method()->size_of_parameters() : method()->max_locals();
373
374 assert(mask_len >= max_locals, "invariant");
375
376 const int length = expressions ? mask_len - max_locals : max_locals;
377 assert(length >= 0, "invariant");
378
379 StackValueCollection* const result = new StackValueCollection(length);
380
381 if (0 == length) {
382 return result;
383 }
384
385 if (expressions) {
386 stack_expressions(result, length, max_locals, oop_mask, fr());
387 } else {
388 stack_locals(result, length, oop_mask, fr());
389 }
390
391 assert(length == result->size(), "invariant");
392
393 return result;
394 }
395
396 void interpretedVFrame::set_locals(StackValueCollection* values) const {
397 if (values == NULL || values->size() == 0) return;
398
399 // If the method is native, max_locals is not telling the truth.
400 // maxlocals then equals the size of parameters
401 const int max_locals = method()->is_native() ?
402 method()->size_of_parameters() : method()->max_locals();
403
404 assert(max_locals == values->size(), "Mismatch between actual stack format and supplied data");
405
282 // handle locals 406 // handle locals
283 for(int i=0; i < length; i++) { 407 for (int i = 0; i < max_locals; i++) {
284 // Find stack location 408 // Find stack location
285 intptr_t *addr = locals_addr_at(i); 409 intptr_t *addr = locals_addr_at(i);
286 410
287 // Depending on oop/int put it in the right package 411 // Depending on oop/int put it in the right package
288 StackValue *sv; 412 const StackValue* const sv = values->at(i);
289 if (oop_mask.is_oop(i)) {
290 // oop value
291 Handle h(*(oop *)addr);
292 sv = new StackValue(h);
293 } else {
294 // integer
295 sv = new StackValue(*addr);
296 }
297 assert(sv != NULL, "sanity check");
298 result->add(sv);
299 }
300 return result;
301 }
302
303 void interpretedVFrame::set_locals(StackValueCollection* values) const {
304 if (values == NULL || values->size() == 0) return;
305
306 int length = method()->max_locals();
307 if (method()->is_native()) {
308 // If the method is native, max_locals is not telling the truth.
309 // maxlocals then equals the size of parameters
310 length = method()->size_of_parameters();
311 }
312
313 assert(length == values->size(), "Mismatch between actual stack format and supplied data");
314
315 // handle locals
316 for (int i = 0; i < length; i++) {
317 // Find stack location
318 intptr_t *addr = locals_addr_at(i);
319
320 // Depending on oop/int put it in the right package
321 StackValue *sv = values->at(i);
322 assert(sv != NULL, "sanity check"); 413 assert(sv != NULL, "sanity check");
323 if (sv->type() == T_OBJECT) { 414 if (sv->type() == T_OBJECT) {
324 *(oop *) addr = (sv->get_obj())(); 415 *(oop *) addr = (sv->get_obj())();
325 } else { // integer 416 } else { // integer
326 *addr = sv->get_int(); 417 *addr = sv->get_int();
327 } 418 }
328 } 419 }
329 } 420 }
330
331 StackValueCollection* interpretedVFrame::expressions() const {
332 int length = fr().interpreter_frame_expression_stack_size();
333 if (method()->is_native()) {
334 // If the method is native, there is no expression stack
335 length = 0;
336 }
337
338 int nof_locals = method()->max_locals();
339 StackValueCollection* result = new StackValueCollection(length);
340
341 InterpreterOopMap oop_mask;
342 // Get oopmap describing oops and int for current bci
343 if (TraceDeoptimization && Verbose) {
344 methodHandle m_h(method());
345 OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
346 } else {
347 method()->mask_for(bci(), &oop_mask);
348 }
349 // handle expressions
350 for(int i=0; i < length; i++) {
351 // Find stack location
352 intptr_t *addr = fr().interpreter_frame_expression_stack_at(i);
353
354 // Depending on oop/int put it in the right package
355 StackValue *sv;
356 if (oop_mask.is_oop(i + nof_locals)) {
357 // oop value
358 Handle h(*(oop *)addr);
359 sv = new StackValue(h);
360 } else {
361 // integer
362 sv = new StackValue(*addr);
363 }
364 assert(sv != NULL, "sanity check");
365 result->add(sv);
366 }
367 return result;
368 }
369
370 421
371 // ------------- cChunk -------------- 422 // ------------- cChunk --------------
372 423
373 entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) 424 entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
374 : externalVFrame(fr, reg_map, thread) {} 425 : externalVFrame(fr, reg_map, thread) {}