Mercurial > hg > truffle
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) {} |