Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: src/arm/codegen-arm.cc

Issue 2815003: ARM: Change code generation for function return... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/virtual-frame-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/virtual-frame-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698