OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; | 335 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
336 if (should_trace) { | 336 if (should_trace) { |
337 frame_->CallRuntime(Runtime::kDebugTrace, 0); | 337 frame_->CallRuntime(Runtime::kDebugTrace, 0); |
338 // Ignore the return value. | 338 // Ignore the return value. |
339 } | 339 } |
340 #endif | 340 #endif |
341 VisitStatements(info->function()->body()); | 341 VisitStatements(info->function()->body()); |
342 } | 342 } |
343 } | 343 } |
344 | 344 |
345 // Generate the return sequence if necessary. | 345 // Handle the return from the function. |
346 if (has_valid_frame() || function_return_.is_linked()) { | 346 if (has_valid_frame()) { |
347 if (!function_return_.is_linked()) { | 347 // If there is a valid frame, control flow can fall off the end of |
348 CodeForReturnPosition(info->function()); | 348 // the body. In that case there is an implicit return statement. |
| 349 ASSERT(!function_return_is_shadowed_); |
| 350 frame_->PrepareForReturn(); |
| 351 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 352 if (function_return_.is_bound()) { |
| 353 function_return_.Jump(); |
| 354 } else { |
| 355 function_return_.Bind(); |
| 356 GenerateReturnSequence(); |
349 } | 357 } |
350 // exit | 358 } else if (function_return_.is_linked()) { |
351 // r0: result | 359 // If the return target has dangling jumps to it, then we have not |
352 // sp: stack pointer | 360 // yet generated the return sequence. This can happen when (a) |
353 // fp: frame pointer | 361 // control does not flow off the end of the body so we did not |
354 // cp: callee's context | 362 // compile an artificial return statement just above, and (b) there |
355 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 363 // are return statements in the body but (c) they are all shadowed. |
356 | |
357 function_return_.Bind(); | 364 function_return_.Bind(); |
358 if (FLAG_trace) { | 365 GenerateReturnSequence(); |
359 // Push the return value on the stack as the parameter. | |
360 // Runtime::TraceExit returns the parameter as it is. | |
361 frame_->EmitPush(r0); | |
362 frame_->CallRuntime(Runtime::kTraceExit, 1); | |
363 } | |
364 | |
365 #ifdef DEBUG | |
366 // Add a label for checking the size of the code used for returning. | |
367 Label check_exit_codesize; | |
368 masm_->bind(&check_exit_codesize); | |
369 #endif | |
370 // Make sure that the constant pool is not emitted inside of the return | |
371 // sequence. | |
372 { Assembler::BlockConstPoolScope block_const_pool(masm_); | |
373 // Tear down the frame which will restore the caller's frame pointer and | |
374 // the link register. | |
375 frame_->Exit(); | |
376 | |
377 // Here we use masm_-> instead of the __ macro to avoid the code coverage | |
378 // tool from instrumenting as we rely on the code size here. | |
379 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; | |
380 masm_->add(sp, sp, Operand(sp_delta)); | |
381 masm_->Jump(lr); | |
382 | |
383 #ifdef DEBUG | |
384 // Check that the size of the code used for returning matches what is | |
385 // expected by the debugger. If the sp_delts above cannot be encoded in | |
386 // the add instruction the add will generate two instructions. | |
387 int return_sequence_length = | |
388 masm_->InstructionsGeneratedSince(&check_exit_codesize); | |
389 CHECK(return_sequence_length == | |
390 Assembler::kJSReturnSequenceInstructions || | |
391 return_sequence_length == | |
392 Assembler::kJSReturnSequenceInstructions + 1); | |
393 #endif | |
394 } | |
395 } | 366 } |
396 | 367 |
397 // Adjust for function-level loop nesting. | 368 // Adjust for function-level loop nesting. |
398 ASSERT(loop_nesting_ == info->loop_nesting()); | 369 ASSERT(loop_nesting_ == info->loop_nesting()); |
399 loop_nesting_ = 0; | 370 loop_nesting_ = 0; |
400 | 371 |
401 // Code generation state must be reset. | 372 // Code generation state must be reset. |
402 ASSERT(!has_cc()); | 373 ASSERT(!has_cc()); |
403 ASSERT(state_ == NULL); | 374 ASSERT(state_ == NULL); |
404 ASSERT(loop_nesting() == 0); | 375 ASSERT(loop_nesting() == 0); |
(...skipping 1546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1951 CodeForStatementPosition(node); | 1922 CodeForStatementPosition(node); |
1952 Load(node->expression()); | 1923 Load(node->expression()); |
1953 if (function_return_is_shadowed_) { | 1924 if (function_return_is_shadowed_) { |
1954 frame_->EmitPop(r0); | 1925 frame_->EmitPop(r0); |
1955 function_return_.Jump(); | 1926 function_return_.Jump(); |
1956 } else { | 1927 } else { |
1957 // Pop the result from the frame and prepare the frame for | 1928 // Pop the result from the frame and prepare the frame for |
1958 // returning thus making it easier to merge. | 1929 // returning thus making it easier to merge. |
1959 frame_->EmitPop(r0); | 1930 frame_->EmitPop(r0); |
1960 frame_->PrepareForReturn(); | 1931 frame_->PrepareForReturn(); |
1961 | 1932 if (function_return_.is_bound()) { |
1962 function_return_.Jump(); | 1933 // If the function return label is already bound we reuse the |
| 1934 // code by jumping to the return site. |
| 1935 function_return_.Jump(); |
| 1936 } else { |
| 1937 function_return_.Bind(); |
| 1938 GenerateReturnSequence(); |
| 1939 } |
1963 } | 1940 } |
1964 } | 1941 } |
1965 | 1942 |
1966 | 1943 |
| 1944 void CodeGenerator::GenerateReturnSequence() { |
| 1945 if (FLAG_trace) { |
| 1946 // Push the return value on the stack as the parameter. |
| 1947 // Runtime::TraceExit returns the parameter as it is. |
| 1948 frame_->EmitPush(r0); |
| 1949 frame_->CallRuntime(Runtime::kTraceExit, 1); |
| 1950 } |
| 1951 |
| 1952 #ifdef DEBUG |
| 1953 // Add a label for checking the size of the code used for returning. |
| 1954 Label check_exit_codesize; |
| 1955 masm_->bind(&check_exit_codesize); |
| 1956 #endif |
| 1957 // Make sure that the constant pool is not emitted inside of the return |
| 1958 // sequence. |
| 1959 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
| 1960 // Tear down the frame which will restore the caller's frame pointer and |
| 1961 // the link register. |
| 1962 frame_->Exit(); |
| 1963 |
| 1964 // Here we use masm_-> instead of the __ macro to avoid the code coverage |
| 1965 // tool from instrumenting as we rely on the code size here. |
| 1966 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; |
| 1967 masm_->add(sp, sp, Operand(sp_delta)); |
| 1968 masm_->Jump(lr); |
| 1969 DeleteFrame(); |
| 1970 |
| 1971 #ifdef DEBUG |
| 1972 // Check that the size of the code used for returning matches what is |
| 1973 // expected by the debugger. If the sp_delts above cannot be encoded in |
| 1974 // the add instruction the add will generate two instructions. |
| 1975 int return_sequence_length = |
| 1976 masm_->InstructionsGeneratedSince(&check_exit_codesize); |
| 1977 CHECK(return_sequence_length == |
| 1978 Assembler::kJSReturnSequenceInstructions || |
| 1979 return_sequence_length == |
| 1980 Assembler::kJSReturnSequenceInstructions + 1); |
| 1981 #endif |
| 1982 } |
| 1983 } |
| 1984 |
| 1985 |
1967 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 1986 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
1968 #ifdef DEBUG | 1987 #ifdef DEBUG |
1969 int original_height = frame_->height(); | 1988 int original_height = frame_->height(); |
1970 #endif | 1989 #endif |
1971 VirtualFrame::SpilledScope spilled_scope(frame_); | 1990 VirtualFrame::SpilledScope spilled_scope(frame_); |
1972 Comment cmnt(masm_, "[ WithEnterStatement"); | 1991 Comment cmnt(masm_, "[ WithEnterStatement"); |
1973 CodeForStatementPosition(node); | 1992 CodeForStatementPosition(node); |
1974 Load(node->expression()); | 1993 Load(node->expression()); |
1975 if (node->is_catch_block()) { | 1994 if (node->is_catch_block()) { |
1976 frame_->CallRuntime(Runtime::kPushCatchContext, 1); | 1995 frame_->CallRuntime(Runtime::kPushCatchContext, 1); |
(...skipping 8561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10538 __ bind(&string_add_runtime); | 10557 __ bind(&string_add_runtime); |
10539 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10558 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10540 } | 10559 } |
10541 | 10560 |
10542 | 10561 |
10543 #undef __ | 10562 #undef __ |
10544 | 10563 |
10545 } } // namespace v8::internal | 10564 } } // namespace v8::internal |
10546 | 10565 |
10547 #endif // V8_TARGET_ARCH_ARM | 10566 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |