mirror of https://github.com/lukechilds/node.git
Browse Source
Reviewed-By: Fedor Indutny <fedor@indutny.com> PR-URL: https://github.com/joyent/node/pull/8476v0.11.15-release
Refael Ackermann
10 years ago
committed by
Fedor Indutny
1662 changed files with 245114 additions and 74654 deletions
@ -0,0 +1,16 @@ |
|||
{ |
|||
"path": ["."], |
|||
"main": "run.js", |
|||
"run_count": 2, |
|||
"results_regexp": "^%s: (.+)$", |
|||
"benchmarks": [ |
|||
{"name": "Richards"}, |
|||
{"name": "DeltaBlue"}, |
|||
{"name": "Crypto"}, |
|||
{"name": "RayTrace"}, |
|||
{"name": "EarleyBoyer"}, |
|||
{"name": "RegExp"}, |
|||
{"name": "Splay"}, |
|||
{"name": "NavierStokes"} |
|||
] |
|||
} |
@ -0,0 +1,69 @@ |
|||
#!/usr/bin/env python |
|||
# Copyright 2014 the V8 project authors. All rights reserved. |
|||
# Redistribution and use in source and binary forms, with or without |
|||
# modification, are permitted provided that the following conditions are |
|||
# met: |
|||
# |
|||
# * Redistributions of source code must retain the above copyright |
|||
# notice, this list of conditions and the following disclaimer. |
|||
# * Redistributions in binary form must reproduce the above |
|||
# copyright notice, this list of conditions and the following |
|||
# disclaimer in the documentation and/or other materials provided |
|||
# with the distribution. |
|||
# * Neither the name of Google Inc. nor the names of its |
|||
# contributors may be used to endorse or promote products derived |
|||
# from this software without specific prior written permission. |
|||
# |
|||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
"""Outputs host CPU architecture in format recognized by gyp.""" |
|||
|
|||
import platform |
|||
import re |
|||
import sys |
|||
|
|||
|
|||
def main(): |
|||
print DoMain([]) |
|||
return 0 |
|||
|
|||
def DoMain(_): |
|||
"""Hook to be called from gyp without starting a separate python |
|||
interpreter.""" |
|||
host_arch = platform.machine() |
|||
|
|||
# Convert machine type to format recognized by gyp. |
|||
if re.match(r'i.86', host_arch) or host_arch == 'i86pc': |
|||
host_arch = 'ia32' |
|||
elif host_arch in ['x86_64', 'amd64']: |
|||
host_arch = 'x64' |
|||
elif host_arch.startswith('arm'): |
|||
host_arch = 'arm' |
|||
elif host_arch == 'aarch64': |
|||
host_arch = 'arm64' |
|||
elif host_arch == 'mips64': |
|||
host_arch = 'mips64el' |
|||
elif host_arch.startswith('mips'): |
|||
host_arch = 'mipsel' |
|||
|
|||
# platform.machine is based on running kernel. It's possible to use 64-bit |
|||
# kernel with 32-bit userland, e.g. to give linker slightly more memory. |
|||
# Distinguish between different userland bitness by querying |
|||
# the python binary. |
|||
if host_arch == 'x64' and platform.architecture()[0] == '32bit': |
|||
host_arch = 'ia32' |
|||
|
|||
return host_arch |
|||
|
|||
if __name__ == '__main__': |
|||
sys.exit(main()) |
@ -0,0 +1,26 @@ |
|||
#!/usr/bin/env python |
|||
# Copyright 2014 the V8 project authors. All rights reserved. |
|||
# Use of this source code is governed by a BSD-style license that can be |
|||
# found in the LICENSE file. |
|||
|
|||
""" |
|||
This file emits the list of reasons why a particular build needs to be clobbered |
|||
(or a list of 'landmines'). |
|||
""" |
|||
|
|||
import sys |
|||
|
|||
|
|||
def main(): |
|||
""" |
|||
ALL LANDMINES ARE EMITTED FROM HERE. |
|||
""" |
|||
print 'Need to clobber after ICU52 roll.' |
|||
print 'Landmines test.' |
|||
print 'Activating MSVS 2013.' |
|||
print 'Revert activation of MSVS 2013.' |
|||
return 0 |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
sys.exit(main()) |
@ -0,0 +1,114 @@ |
|||
# Copyright 2014 the V8 project authors. All rights reserved. |
|||
# Use of this source code is governed by a BSD-style license that can be |
|||
# found in the LICENSE file. |
|||
|
|||
|
|||
import functools |
|||
import logging |
|||
import os |
|||
import shlex |
|||
import sys |
|||
|
|||
|
|||
def memoize(default=None): |
|||
"""This decorator caches the return value of a parameterless pure function""" |
|||
def memoizer(func): |
|||
val = [] |
|||
@functools.wraps(func) |
|||
def inner(): |
|||
if not val: |
|||
ret = func() |
|||
val.append(ret if ret is not None else default) |
|||
if logging.getLogger().isEnabledFor(logging.INFO): |
|||
print '%s -> %r' % (func.__name__, val[0]) |
|||
return val[0] |
|||
return inner |
|||
return memoizer |
|||
|
|||
|
|||
@memoize() |
|||
def IsWindows(): |
|||
return sys.platform in ['win32', 'cygwin'] |
|||
|
|||
|
|||
@memoize() |
|||
def IsLinux(): |
|||
return sys.platform.startswith(('linux', 'freebsd')) |
|||
|
|||
|
|||
@memoize() |
|||
def IsMac(): |
|||
return sys.platform == 'darwin' |
|||
|
|||
|
|||
@memoize() |
|||
def gyp_defines(): |
|||
"""Parses and returns GYP_DEFINES env var as a dictionary.""" |
|||
return dict(arg.split('=', 1) |
|||
for arg in shlex.split(os.environ.get('GYP_DEFINES', ''))) |
|||
|
|||
@memoize() |
|||
def gyp_msvs_version(): |
|||
return os.environ.get('GYP_MSVS_VERSION', '') |
|||
|
|||
@memoize() |
|||
def distributor(): |
|||
""" |
|||
Returns a string which is the distributed build engine in use (if any). |
|||
Possible values: 'goma', 'ib', '' |
|||
""" |
|||
if 'goma' in gyp_defines(): |
|||
return 'goma' |
|||
elif IsWindows(): |
|||
if 'CHROME_HEADLESS' in os.environ: |
|||
return 'ib' # use (win and !goma and headless) as approximation of ib |
|||
|
|||
|
|||
@memoize() |
|||
def platform(): |
|||
""" |
|||
Returns a string representing the platform this build is targetted for. |
|||
Possible values: 'win', 'mac', 'linux', 'ios', 'android' |
|||
""" |
|||
if 'OS' in gyp_defines(): |
|||
if 'android' in gyp_defines()['OS']: |
|||
return 'android' |
|||
else: |
|||
return gyp_defines()['OS'] |
|||
elif IsWindows(): |
|||
return 'win' |
|||
elif IsLinux(): |
|||
return 'linux' |
|||
else: |
|||
return 'mac' |
|||
|
|||
|
|||
@memoize() |
|||
def builder(): |
|||
""" |
|||
Returns a string representing the build engine (not compiler) to use. |
|||
Possible values: 'make', 'ninja', 'xcode', 'msvs', 'scons' |
|||
""" |
|||
if 'GYP_GENERATORS' in os.environ: |
|||
# for simplicity, only support the first explicit generator |
|||
generator = os.environ['GYP_GENERATORS'].split(',')[0] |
|||
if generator.endswith('-android'): |
|||
return generator.split('-')[0] |
|||
elif generator.endswith('-ninja'): |
|||
return 'ninja' |
|||
else: |
|||
return generator |
|||
else: |
|||
if platform() == 'android': |
|||
# Good enough for now? Do any android bots use make? |
|||
return 'make' |
|||
elif platform() == 'ios': |
|||
return 'xcode' |
|||
elif IsWindows(): |
|||
return 'msvs' |
|||
elif IsLinux(): |
|||
return 'make' |
|||
elif IsMac(): |
|||
return 'xcode' |
|||
else: |
|||
assert False, 'Don\'t know what builder we\'re using!' |
@ -0,0 +1,139 @@ |
|||
#!/usr/bin/env python |
|||
# Copyright 2014 the V8 project authors. All rights reserved. |
|||
# Use of this source code is governed by a BSD-style license that can be |
|||
# found in the LICENSE file. |
|||
|
|||
""" |
|||
This script runs every build as a hook. If it detects that the build should |
|||
be clobbered, it will touch the file <build_dir>/.landmine_triggered. The |
|||
various build scripts will then check for the presence of this file and clobber |
|||
accordingly. The script will also emit the reasons for the clobber to stdout. |
|||
|
|||
A landmine is tripped when a builder checks out a different revision, and the |
|||
diff between the new landmines and the old ones is non-null. At this point, the |
|||
build is clobbered. |
|||
""" |
|||
|
|||
import difflib |
|||
import logging |
|||
import optparse |
|||
import os |
|||
import sys |
|||
import subprocess |
|||
import time |
|||
|
|||
import landmine_utils |
|||
|
|||
|
|||
SRC_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) |
|||
|
|||
|
|||
def get_target_build_dir(build_tool, target): |
|||
""" |
|||
Returns output directory absolute path dependent on build and targets. |
|||
Examples: |
|||
r'c:\b\build\slave\win\build\src\out\Release' |
|||
'/mnt/data/b/build/slave/linux/build/src/out/Debug' |
|||
'/b/build/slave/ios_rel_device/build/src/xcodebuild/Release-iphoneos' |
|||
|
|||
Keep this function in sync with tools/build/scripts/slave/compile.py |
|||
""" |
|||
ret = None |
|||
if build_tool == 'xcode': |
|||
ret = os.path.join(SRC_DIR, 'xcodebuild', target) |
|||
elif build_tool in ['make', 'ninja', 'ninja-ios']: # TODO: Remove ninja-ios. |
|||
ret = os.path.join(SRC_DIR, 'out', target) |
|||
elif build_tool in ['msvs', 'vs', 'ib']: |
|||
ret = os.path.join(SRC_DIR, 'build', target) |
|||
else: |
|||
raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool) |
|||
return os.path.abspath(ret) |
|||
|
|||
|
|||
def set_up_landmines(target, new_landmines): |
|||
"""Does the work of setting, planting, and triggering landmines.""" |
|||
out_dir = get_target_build_dir(landmine_utils.builder(), target) |
|||
|
|||
landmines_path = os.path.join(out_dir, '.landmines') |
|||
if not os.path.exists(out_dir): |
|||
return |
|||
|
|||
if not os.path.exists(landmines_path): |
|||
print "Landmines tracker didn't exists." |
|||
|
|||
# FIXME(machenbach): Clobber deletes the .landmines tracker. Difficult |
|||
# to know if we are right after a clobber or if it is first-time landmines |
|||
# deployment. Also, a landmine-triggered clobber right after a clobber is |
|||
# not possible. Different clobber methods for msvs, xcode and make all |
|||
# have different blacklists of files that are not deleted. |
|||
if os.path.exists(landmines_path): |
|||
triggered = os.path.join(out_dir, '.landmines_triggered') |
|||
with open(landmines_path, 'r') as f: |
|||
old_landmines = f.readlines() |
|||
if old_landmines != new_landmines: |
|||
old_date = time.ctime(os.stat(landmines_path).st_ctime) |
|||
diff = difflib.unified_diff(old_landmines, new_landmines, |
|||
fromfile='old_landmines', tofile='new_landmines', |
|||
fromfiledate=old_date, tofiledate=time.ctime(), n=0) |
|||
|
|||
with open(triggered, 'w') as f: |
|||
f.writelines(diff) |
|||
print "Setting landmine: %s" % triggered |
|||
elif os.path.exists(triggered): |
|||
# Remove false triggered landmines. |
|||
os.remove(triggered) |
|||
print "Removing landmine: %s" % triggered |
|||
with open(landmines_path, 'w') as f: |
|||
f.writelines(new_landmines) |
|||
|
|||
|
|||
def process_options(): |
|||
"""Returns a list of landmine emitting scripts.""" |
|||
parser = optparse.OptionParser() |
|||
parser.add_option( |
|||
'-s', '--landmine-scripts', action='append', |
|||
default=[os.path.join(SRC_DIR, 'build', 'get_landmines.py')], |
|||
help='Path to the script which emits landmines to stdout. The target ' |
|||
'is passed to this script via option -t. Note that an extra ' |
|||
'script can be specified via an env var EXTRA_LANDMINES_SCRIPT.') |
|||
parser.add_option('-v', '--verbose', action='store_true', |
|||
default=('LANDMINES_VERBOSE' in os.environ), |
|||
help=('Emit some extra debugging information (default off). This option ' |
|||
'is also enabled by the presence of a LANDMINES_VERBOSE environment ' |
|||
'variable.')) |
|||
|
|||
options, args = parser.parse_args() |
|||
|
|||
if args: |
|||
parser.error('Unknown arguments %s' % args) |
|||
|
|||
logging.basicConfig( |
|||
level=logging.DEBUG if options.verbose else logging.ERROR) |
|||
|
|||
extra_script = os.environ.get('EXTRA_LANDMINES_SCRIPT') |
|||
if extra_script: |
|||
return options.landmine_scripts + [extra_script] |
|||
else: |
|||
return options.landmine_scripts |
|||
|
|||
|
|||
def main(): |
|||
landmine_scripts = process_options() |
|||
|
|||
if landmine_utils.builder() in ('dump_dependency_json', 'eclipse'): |
|||
return 0 |
|||
|
|||
landmines = [] |
|||
for s in landmine_scripts: |
|||
proc = subprocess.Popen([sys.executable, s], stdout=subprocess.PIPE) |
|||
output, _ = proc.communicate() |
|||
landmines.extend([('%s\n' % l.strip()) for l in output.splitlines()]) |
|||
|
|||
for target in ('Debug', 'Release'): |
|||
set_up_landmines(target, landmines) |
|||
|
|||
return 0 |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
sys.exit(main()) |
@ -0,0 +1,38 @@ |
|||
// Copyright 2014 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#ifndef V8_LIBPLATFORM_LIBPLATFORM_H_ |
|||
#define V8_LIBPLATFORM_LIBPLATFORM_H_ |
|||
|
|||
#include "include/v8-platform.h" |
|||
|
|||
namespace v8 { |
|||
namespace platform { |
|||
|
|||
/**
|
|||
* Returns a new instance of the default v8::Platform implementation. |
|||
* |
|||
* The caller will take ownership of the returned pointer. |thread_pool_size| |
|||
* is the number of worker threads to allocate for background jobs. If a value |
|||
* of zero is passed, a suitable default based on the current number of |
|||
* processors online will be chosen. |
|||
*/ |
|||
v8::Platform* CreateDefaultPlatform(int thread_pool_size = 0); |
|||
|
|||
|
|||
/**
|
|||
* Pumps the message loop for the given isolate. |
|||
* |
|||
* The caller has to make sure that this is called from the right thread. |
|||
* Returns true if a task was executed, and false otherwise. This call does |
|||
* not block if no task is pending. The |platform| has to be created using |
|||
* |CreateDefaultPlatform|. |
|||
*/ |
|||
bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate); |
|||
|
|||
|
|||
} // namespace platform
|
|||
} // namespace v8
|
|||
|
|||
#endif // V8_LIBPLATFORM_LIBPLATFORM_H_
|
@ -0,0 +1,13 @@ |
|||
include_rules = [ |
|||
"+src", |
|||
"-src/compiler", |
|||
"+src/compiler/pipeline.h", |
|||
"-src/libplatform", |
|||
"-include/libplatform", |
|||
] |
|||
|
|||
specific_include_rules = { |
|||
"(mksnapshot|d8)\.cc": [ |
|||
"+include/libplatform/libplatform.h", |
|||
], |
|||
} |
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -1,71 +0,0 @@ |
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#ifndef V8_ARM64_CPU_ARM64_H_ |
|||
#define V8_ARM64_CPU_ARM64_H_ |
|||
|
|||
#include <stdio.h> |
|||
#include "serialize.h" |
|||
#include "cpu.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
|
|||
// CpuFeatures keeps track of which features are supported by the target CPU.
|
|||
// Supported features must be enabled by a CpuFeatureScope before use.
|
|||
class CpuFeatures : public AllStatic { |
|||
public: |
|||
// Detect features of the target CPU. Set safe defaults if the serializer
|
|||
// is enabled (snapshots must be portable).
|
|||
static void Probe(bool serializer_enabled); |
|||
|
|||
// Check whether a feature is supported by the target CPU.
|
|||
static bool IsSupported(CpuFeature f) { |
|||
ASSERT(initialized_); |
|||
// There are no optional features for ARM64.
|
|||
return false; |
|||
}; |
|||
|
|||
// There are no optional features for ARM64.
|
|||
static bool IsSafeForSnapshot(Isolate* isolate, CpuFeature f) { |
|||
return IsSupported(f); |
|||
} |
|||
|
|||
// I and D cache line size in bytes.
|
|||
static unsigned dcache_line_size(); |
|||
static unsigned icache_line_size(); |
|||
|
|||
static unsigned supported_; |
|||
|
|||
static bool VerifyCrossCompiling() { |
|||
// There are no optional features for ARM64.
|
|||
ASSERT(cross_compile_ == 0); |
|||
return true; |
|||
} |
|||
|
|||
static bool VerifyCrossCompiling(CpuFeature f) { |
|||
// There are no optional features for ARM64.
|
|||
USE(f); |
|||
ASSERT(cross_compile_ == 0); |
|||
return true; |
|||
} |
|||
|
|||
static bool SupportsCrankshaft() { return true; } |
|||
|
|||
private: |
|||
#ifdef DEBUG |
|||
static bool initialized_; |
|||
#endif |
|||
|
|||
// This isn't used (and is always 0), but it is required by V8.
|
|||
static unsigned cross_compile_; |
|||
|
|||
friend class PlatformFeatureScope; |
|||
DISALLOW_COPY_AND_ASSIGN(CpuFeatures); |
|||
}; |
|||
|
|||
} } // namespace v8::internal
|
|||
|
|||
#endif // V8_ARM64_CPU_ARM64_H_
|
@ -0,0 +1,55 @@ |
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#ifndef V8_ARM64_DELAYED_MASM_ARM64_INL_H_ |
|||
#define V8_ARM64_DELAYED_MASM_ARM64_INL_H_ |
|||
|
|||
#include "src/arm64/delayed-masm-arm64.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
#define __ ACCESS_MASM(masm_) |
|||
|
|||
|
|||
void DelayedMasm::EndDelayedUse() { |
|||
EmitPending(); |
|||
DCHECK(!scratch_register_acquired_); |
|||
ResetSavedValue(); |
|||
} |
|||
|
|||
|
|||
void DelayedMasm::Mov(const Register& rd, |
|||
const Operand& operand, |
|||
DiscardMoveMode discard_mode) { |
|||
EmitPending(); |
|||
DCHECK(!IsScratchRegister(rd) || scratch_register_acquired_); |
|||
__ Mov(rd, operand, discard_mode); |
|||
} |
|||
|
|||
|
|||
void DelayedMasm::Fmov(FPRegister fd, FPRegister fn) { |
|||
EmitPending(); |
|||
__ Fmov(fd, fn); |
|||
} |
|||
|
|||
|
|||
void DelayedMasm::Fmov(FPRegister fd, double imm) { |
|||
EmitPending(); |
|||
__ Fmov(fd, imm); |
|||
} |
|||
|
|||
|
|||
void DelayedMasm::LoadObject(Register result, Handle<Object> object) { |
|||
EmitPending(); |
|||
DCHECK(!IsScratchRegister(result) || scratch_register_acquired_); |
|||
__ LoadObject(result, object); |
|||
} |
|||
|
|||
|
|||
#undef __ |
|||
|
|||
} } // namespace v8::internal
|
|||
|
|||
#endif // V8_ARM64_DELAYED_MASM_ARM64_INL_H_
|
@ -0,0 +1,198 @@ |
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "src/v8.h" |
|||
|
|||
#if V8_TARGET_ARCH_ARM64 |
|||
|
|||
#include "src/arm64/delayed-masm-arm64.h" |
|||
#include "src/arm64/lithium-codegen-arm64.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
#define __ ACCESS_MASM(masm_) |
|||
|
|||
|
|||
void DelayedMasm::StackSlotMove(LOperand* src, LOperand* dst) { |
|||
DCHECK(src->IsStackSlot()); |
|||
DCHECK(dst->IsStackSlot()); |
|||
MemOperand src_operand = cgen_->ToMemOperand(src); |
|||
MemOperand dst_operand = cgen_->ToMemOperand(dst); |
|||
if (pending_ == kStackSlotMove) { |
|||
DCHECK(pending_pc_ == masm_->pc_offset()); |
|||
UseScratchRegisterScope scope(masm_); |
|||
DoubleRegister temp1 = scope.AcquireD(); |
|||
DoubleRegister temp2 = scope.AcquireD(); |
|||
switch (MemOperand::AreConsistentForPair(pending_address_src_, |
|||
src_operand)) { |
|||
case MemOperand::kNotPair: |
|||
__ Ldr(temp1, pending_address_src_); |
|||
__ Ldr(temp2, src_operand); |
|||
break; |
|||
case MemOperand::kPairAB: |
|||
__ Ldp(temp1, temp2, pending_address_src_); |
|||
break; |
|||
case MemOperand::kPairBA: |
|||
__ Ldp(temp2, temp1, src_operand); |
|||
break; |
|||
} |
|||
switch (MemOperand::AreConsistentForPair(pending_address_dst_, |
|||
dst_operand)) { |
|||
case MemOperand::kNotPair: |
|||
__ Str(temp1, pending_address_dst_); |
|||
__ Str(temp2, dst_operand); |
|||
break; |
|||
case MemOperand::kPairAB: |
|||
__ Stp(temp1, temp2, pending_address_dst_); |
|||
break; |
|||
case MemOperand::kPairBA: |
|||
__ Stp(temp2, temp1, dst_operand); |
|||
break; |
|||
} |
|||
ResetPending(); |
|||
return; |
|||
} |
|||
|
|||
EmitPending(); |
|||
pending_ = kStackSlotMove; |
|||
pending_address_src_ = src_operand; |
|||
pending_address_dst_ = dst_operand; |
|||
#ifdef DEBUG |
|||
pending_pc_ = masm_->pc_offset(); |
|||
#endif |
|||
} |
|||
|
|||
|
|||
void DelayedMasm::StoreConstant(uint64_t value, const MemOperand& operand) { |
|||
DCHECK(!scratch_register_acquired_); |
|||
if ((pending_ == kStoreConstant) && (value == pending_value_)) { |
|||
MemOperand::PairResult result = |
|||
MemOperand::AreConsistentForPair(pending_address_dst_, operand); |
|||
if (result != MemOperand::kNotPair) { |
|||
const MemOperand& dst = |
|||
(result == MemOperand::kPairAB) ? |
|||
pending_address_dst_ : |
|||
operand; |
|||
DCHECK(pending_pc_ == masm_->pc_offset()); |
|||
if (pending_value_ == 0) { |
|||
__ Stp(xzr, xzr, dst); |
|||
} else { |
|||
SetSavedValue(pending_value_); |
|||
__ Stp(ScratchRegister(), ScratchRegister(), dst); |
|||
} |
|||
ResetPending(); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
EmitPending(); |
|||
pending_ = kStoreConstant; |
|||
pending_address_dst_ = operand; |
|||
pending_value_ = value; |
|||
#ifdef DEBUG |
|||
pending_pc_ = masm_->pc_offset(); |
|||
#endif |
|||
} |
|||
|
|||
|
|||
void DelayedMasm::Load(const CPURegister& rd, const MemOperand& operand) { |
|||
if ((pending_ == kLoad) && |
|||
pending_register_.IsSameSizeAndType(rd)) { |
|||
switch (MemOperand::AreConsistentForPair(pending_address_src_, operand)) { |
|||
case MemOperand::kNotPair: |
|||
break; |
|||
case MemOperand::kPairAB: |
|||
DCHECK(pending_pc_ == masm_->pc_offset()); |
|||
DCHECK(!IsScratchRegister(pending_register_) || |
|||
scratch_register_acquired_); |
|||
DCHECK(!IsScratchRegister(rd) || scratch_register_acquired_); |
|||
__ Ldp(pending_register_, rd, pending_address_src_); |
|||
ResetPending(); |
|||
return; |
|||
case MemOperand::kPairBA: |
|||
DCHECK(pending_pc_ == masm_->pc_offset()); |
|||
DCHECK(!IsScratchRegister(pending_register_) || |
|||
scratch_register_acquired_); |
|||
DCHECK(!IsScratchRegister(rd) || scratch_register_acquired_); |
|||
__ Ldp(rd, pending_register_, operand); |
|||
ResetPending(); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
EmitPending(); |
|||
pending_ = kLoad; |
|||
pending_register_ = rd; |
|||
pending_address_src_ = operand; |
|||
#ifdef DEBUG |
|||
pending_pc_ = masm_->pc_offset(); |
|||
#endif |
|||
} |
|||
|
|||
|
|||
void DelayedMasm::Store(const CPURegister& rd, const MemOperand& operand) { |
|||
if ((pending_ == kStore) && |
|||
pending_register_.IsSameSizeAndType(rd)) { |
|||
switch (MemOperand::AreConsistentForPair(pending_address_dst_, operand)) { |
|||
case MemOperand::kNotPair: |
|||
break; |
|||
case MemOperand::kPairAB: |
|||
DCHECK(pending_pc_ == masm_->pc_offset()); |
|||
__ Stp(pending_register_, rd, pending_address_dst_); |
|||
ResetPending(); |
|||
return; |
|||
case MemOperand::kPairBA: |
|||
DCHECK(pending_pc_ == masm_->pc_offset()); |
|||
__ Stp(rd, pending_register_, operand); |
|||
ResetPending(); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
EmitPending(); |
|||
pending_ = kStore; |
|||
pending_register_ = rd; |
|||
pending_address_dst_ = operand; |
|||
#ifdef DEBUG |
|||
pending_pc_ = masm_->pc_offset(); |
|||
#endif |
|||
} |
|||
|
|||
|
|||
void DelayedMasm::EmitPending() { |
|||
DCHECK((pending_ == kNone) || (pending_pc_ == masm_->pc_offset())); |
|||
switch (pending_) { |
|||
case kNone: |
|||
return; |
|||
case kStoreConstant: |
|||
if (pending_value_ == 0) { |
|||
__ Str(xzr, pending_address_dst_); |
|||
} else { |
|||
SetSavedValue(pending_value_); |
|||
__ Str(ScratchRegister(), pending_address_dst_); |
|||
} |
|||
break; |
|||
case kLoad: |
|||
DCHECK(!IsScratchRegister(pending_register_) || |
|||
scratch_register_acquired_); |
|||
__ Ldr(pending_register_, pending_address_src_); |
|||
break; |
|||
case kStore: |
|||
__ Str(pending_register_, pending_address_dst_); |
|||
break; |
|||
case kStackSlotMove: { |
|||
UseScratchRegisterScope scope(masm_); |
|||
DoubleRegister temp = scope.AcquireD(); |
|||
__ Ldr(temp, pending_address_src_); |
|||
__ Str(temp, pending_address_dst_); |
|||
break; |
|||
} |
|||
} |
|||
ResetPending(); |
|||
} |
|||
|
|||
} } // namespace v8::internal
|
|||
|
|||
#endif // V8_TARGET_ARCH_ARM64
|
@ -0,0 +1,164 @@ |
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#ifndef V8_ARM64_DELAYED_MASM_ARM64_H_ |
|||
#define V8_ARM64_DELAYED_MASM_ARM64_H_ |
|||
|
|||
#include "src/lithium.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
class LCodeGen; |
|||
|
|||
// This class delays the generation of some instructions. This way, we have a
|
|||
// chance to merge two instructions in one (with load/store pair).
|
|||
// Each instruction must either:
|
|||
// - merge with the pending instruction and generate just one instruction.
|
|||
// - emit the pending instruction and then generate the instruction (or set the
|
|||
// pending instruction).
|
|||
class DelayedMasm BASE_EMBEDDED { |
|||
public: |
|||
DelayedMasm(LCodeGen* owner, |
|||
MacroAssembler* masm, |
|||
const Register& scratch_register) |
|||
: cgen_(owner), masm_(masm), scratch_register_(scratch_register), |
|||
scratch_register_used_(false), pending_(kNone), saved_value_(0) { |
|||
#ifdef DEBUG |
|||
pending_register_ = no_reg; |
|||
pending_value_ = 0; |
|||
pending_pc_ = 0; |
|||
scratch_register_acquired_ = false; |
|||
#endif |
|||
} |
|||
~DelayedMasm() { |
|||
DCHECK(!scratch_register_acquired_); |
|||
DCHECK(!scratch_register_used_); |
|||
DCHECK(!pending()); |
|||
} |
|||
inline void EndDelayedUse(); |
|||
|
|||
const Register& ScratchRegister() { |
|||
scratch_register_used_ = true; |
|||
return scratch_register_; |
|||
} |
|||
bool IsScratchRegister(const CPURegister& reg) { |
|||
return reg.Is(scratch_register_); |
|||
} |
|||
bool scratch_register_used() const { return scratch_register_used_; } |
|||
void reset_scratch_register_used() { scratch_register_used_ = false; } |
|||
// Acquire/Release scratch register for use outside this class.
|
|||
void AcquireScratchRegister() { |
|||
EmitPending(); |
|||
ResetSavedValue(); |
|||
#ifdef DEBUG |
|||
DCHECK(!scratch_register_acquired_); |
|||
scratch_register_acquired_ = true; |
|||
#endif |
|||
} |
|||
void ReleaseScratchRegister() { |
|||
#ifdef DEBUG |
|||
DCHECK(scratch_register_acquired_); |
|||
scratch_register_acquired_ = false; |
|||
#endif |
|||
} |
|||
bool pending() { return pending_ != kNone; } |
|||
|
|||
// Extra layer over the macro-assembler instructions (which emits the
|
|||
// potential pending instruction).
|
|||
inline void Mov(const Register& rd, |
|||
const Operand& operand, |
|||
DiscardMoveMode discard_mode = kDontDiscardForSameWReg); |
|||
inline void Fmov(FPRegister fd, FPRegister fn); |
|||
inline void Fmov(FPRegister fd, double imm); |
|||
inline void LoadObject(Register result, Handle<Object> object); |
|||
// Instructions which try to merge which the pending instructions.
|
|||
void StackSlotMove(LOperand* src, LOperand* dst); |
|||
// StoreConstant can only be used if the scratch register is not acquired.
|
|||
void StoreConstant(uint64_t value, const MemOperand& operand); |
|||
void Load(const CPURegister& rd, const MemOperand& operand); |
|||
void Store(const CPURegister& rd, const MemOperand& operand); |
|||
// Emit the potential pending instruction.
|
|||
void EmitPending(); |
|||
// Reset the pending state.
|
|||
void ResetPending() { |
|||
pending_ = kNone; |
|||
#ifdef DEBUG |
|||
pending_register_ = no_reg; |
|||
MemOperand tmp; |
|||
pending_address_src_ = tmp; |
|||
pending_address_dst_ = tmp; |
|||
pending_value_ = 0; |
|||
pending_pc_ = 0; |
|||
#endif |
|||
} |
|||
void InitializeRootRegister() { |
|||
masm_->InitializeRootRegister(); |
|||
} |
|||
|
|||
private: |
|||
// Set the saved value and load the ScratchRegister with it.
|
|||
void SetSavedValue(uint64_t saved_value) { |
|||
DCHECK(saved_value != 0); |
|||
if (saved_value_ != saved_value) { |
|||
masm_->Mov(ScratchRegister(), saved_value); |
|||
saved_value_ = saved_value; |
|||
} |
|||
} |
|||
// Reset the saved value (i.e. the value of ScratchRegister is no longer
|
|||
// known).
|
|||
void ResetSavedValue() { |
|||
saved_value_ = 0; |
|||
} |
|||
|
|||
LCodeGen* cgen_; |
|||
MacroAssembler* masm_; |
|||
|
|||
// Register used to store a constant.
|
|||
Register scratch_register_; |
|||
bool scratch_register_used_; |
|||
|
|||
// Sometimes we store or load two values in two contiguous stack slots.
|
|||
// In this case, we try to use the ldp/stp instructions to reduce code size.
|
|||
// To be able to do that, instead of generating directly the instructions,
|
|||
// we register with the following fields that an instruction needs to be
|
|||
// generated. Then with the next instruction, if the instruction is
|
|||
// consistent with the pending one for stp/ldp we generate ldp/stp. Else,
|
|||
// if they are not consistent, we generate the pending instruction and we
|
|||
// register the new instruction (which becomes pending).
|
|||
|
|||
// Enumeration of instructions which can be pending.
|
|||
enum Pending { |
|||
kNone, |
|||
kStoreConstant, |
|||
kLoad, kStore, |
|||
kStackSlotMove |
|||
}; |
|||
// The pending instruction.
|
|||
Pending pending_; |
|||
// For kLoad, kStore: register which must be loaded/stored.
|
|||
CPURegister pending_register_; |
|||
// For kLoad, kStackSlotMove: address of the load.
|
|||
MemOperand pending_address_src_; |
|||
// For kStoreConstant, kStore, kStackSlotMove: address of the store.
|
|||
MemOperand pending_address_dst_; |
|||
// For kStoreConstant: value to be stored.
|
|||
uint64_t pending_value_; |
|||
// Value held into the ScratchRegister if the saved_value_ is not 0.
|
|||
// For 0, we use xzr.
|
|||
uint64_t saved_value_; |
|||
#ifdef DEBUG |
|||
// Address where the pending instruction must be generated. It's only used to
|
|||
// check that nothing else has been generated since we set the pending
|
|||
// instruction.
|
|||
int pending_pc_; |
|||
// If true, the scratch register has been acquired outside this class. The
|
|||
// scratch register can no longer be used for constants.
|
|||
bool scratch_register_acquired_; |
|||
#endif |
|||
}; |
|||
|
|||
} } // namespace v8::internal
|
|||
|
|||
#endif // V8_ARM64_DELAYED_MASM_ARM64_H_
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue